]> granicus.if.org Git - php/commitdiff
added experimental enum support
authorHarald Radi <phanto@php.net>
Mon, 11 Jun 2001 23:05:32 +0000 (23:05 +0000)
committerHarald Radi <phanto@php.net>
Mon, 11 Jun 2001 23:05:32 +0000 (23:05 +0000)
changed everthing to use the Z_* makros

ext/com/COM.c
ext/com/com.h
ext/com/conversion.c
ext/rpc/com/com_wrapper.c
ext/rpc/com/com_wrapper.h
ext/rpc/com/conversion.c

index 9bd8f0983f67ae6f199fe56f6058d60be1854108..9550113a06aa3b6e5542941a2b06cde5fdbfe97d 100644 (file)
@@ -72,6 +72,7 @@ PHP_FUNCTION(com_release);
 PHP_FUNCTION(com_propget);
 PHP_FUNCTION(com_propput);
 PHP_FUNCTION(com_load_typelib);
+PHP_FUNCTION(com_isenum);
 
 PHPAPI int php_COM_get_le_idispatch();
 static ITypeLib *php_COM_find_typelib(char *search_string, int mode);
@@ -84,16 +85,20 @@ function_entry COM_functions[] = {
        PHP_FE(com_load,                                NULL)
        PHP_FE(com_invoke,                              NULL)
        PHP_FE(com_addref,                              NULL)
-       PHP_FE(com_release,                                     NULL)
+       PHP_FE(com_release,                             NULL)
        PHP_FE(com_propget,                             NULL)
        PHP_FE(com_propput,                             NULL)
        PHP_FE(com_load_typelib,                        NULL)
+       PHP_FE(com_isenum,                              NULL)
 
        PHP_FALIAS(com_get,         com_propget,        NULL)
        PHP_FALIAS(com_propset,     com_propput,        NULL)
        PHP_FALIAS(com_set,         com_propput,        NULL)
 
-       {NULL, NULL, NULL}
+       
+       {
+               NULL, NULL, NULL
+       }
 };
 
 static PHP_MINFO_FUNCTION(COM)
@@ -101,21 +106,19 @@ static PHP_MINFO_FUNCTION(COM)
        DISPLAY_INI_ENTRIES();
 }
 
-PHPAPI HRESULT php_COM_invoke(i_dispatch *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)
 {
        HRESULT hr;
        int failed = FALSE;
 
-       if(obj->referenced)
+       if(C_ISREFD(obj))
        {
-               if(obj->typelib)
+               if(C_HASTLIB(obj))
                {
-                       hr = obj->i.typeinfo->lpVtbl->Invoke(obj->i.typeinfo, obj->i.dispatch, dispIdMember,
-                                                                                                  wFlags, pDispParams, pVarResult, NULL, NULL);
+                       hr = C_TYPEINFO_VT(obj)->Invoke(C_TYPEINFO(obj), C_DISPATCH(obj), dispIdMember, wFlags, pDispParams, pVarResult, NULL, NULL);
                        if(FAILED(hr))
                        {
-                               hr = obj->i.dispatch->lpVtbl->Invoke(obj->i.dispatch, 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, NULL, NULL);
                                if(SUCCEEDED(hr))
                                {
                                        /*
@@ -123,15 +126,14 @@ PHPAPI HRESULT php_COM_invoke(i_dispatch *obj, DISPID dispIdMember, WORD wFlags,
                                         * Release ITypeLib and fall back to IDispatch
                                         */
 
-                                       obj->i.typeinfo->lpVtbl->Release(obj->i.typeinfo);
-                                       obj->typelib = FALSE;
+                                       C_TYPEINFO_VT(obj)->Release(C_TYPEINFO(obj));
+                                       C_HASTLIB(obj) = FALSE;
                                }
                        }
                }
                else
                {
-                       hr = obj->i.dispatch->lpVtbl->Invoke(obj->i.dispatch, 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, NULL, NULL);
                }
 
                return hr;
@@ -142,19 +144,19 @@ PHPAPI HRESULT php_COM_invoke(i_dispatch *obj, DISPID dispIdMember, WORD wFlags,
        }
 }
 
-PHPAPI HRESULT php_COM_get_ids_of_names(i_dispatch *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)
 {
        HRESULT hr;
 
-       if(obj->referenced)
+       if(C_ISREFD(obj))
        {
-               if(obj->typelib)
+               if(C_HASTLIB(obj))
                {
-                       hr = obj->i.typeinfo->lpVtbl->GetIDsOfNames(obj->i.typeinfo, rgszNames, 1, rgDispId);
+                       hr = C_TYPEINFO_VT(obj)->GetIDsOfNames(C_TYPEINFO(obj), rgszNames, 1, rgDispId);
 
                        if(FAILED(hr))
                        {
-                               hr = obj->i.dispatch->lpVtbl->GetIDsOfNames(obj->i.dispatch, &IID_NULL, rgszNames, 1, LOCALE_SYSTEM_DEFAULT, rgDispId);
+                               hr = C_DISPATCH_VT(obj)->GetIDsOfNames(C_DISPATCH(obj), &IID_NULL, rgszNames, 1, LOCALE_SYSTEM_DEFAULT, rgDispId);
 
                                if(SUCCEEDED(hr))
                                {
@@ -163,14 +165,14 @@ PHPAPI HRESULT php_COM_get_ids_of_names(i_dispatch *obj, OLECHAR FAR* FAR* rgszN
                                         * Release ITypeLib and fall back to IDispatch
                                         */
 
-                                       obj->i.typeinfo->lpVtbl->Release(obj->i.typeinfo);
-                                       obj->typelib = FALSE;
+                                       C_TYPEINFO_VT(obj)->Release(C_TYPEINFO(obj));
+                                       C_HASTLIB(obj) = FALSE;
                                }
                        }
                }
                else
                {
-                       hr = obj->i.dispatch->lpVtbl->GetIDsOfNames(obj->i.dispatch, &IID_NULL, rgszNames, 1, LOCALE_SYSTEM_DEFAULT, rgDispId);
+                       hr = C_DISPATCH_VT(obj)->GetIDsOfNames(C_DISPATCH(obj), &IID_NULL, rgszNames, 1, LOCALE_SYSTEM_DEFAULT, rgDispId);
                }
 
                return hr;
@@ -181,72 +183,104 @@ PHPAPI HRESULT php_COM_get_ids_of_names(i_dispatch *obj, OLECHAR FAR* FAR* rgszN
        }
 }
 
-PHPAPI HRESULT php_COM_release(i_dispatch *obj)
+PHPAPI HRESULT php_COM_release(comval *obj)
 {
-       if(obj->referenced > 1)
+       if(obj->refcount > 1)
        {
-               obj->referenced--;
+               C_RELEASE(obj);
        }
-       else if(obj->referenced == 1)
+       else if(obj->refcount == 1)
        {
-               if(obj->typelib)
+               if(C_HASTLIB(obj))
                {
-                       obj->i.typeinfo->lpVtbl->Release(obj->i.typeinfo);
+                       C_TYPEINFO_VT(obj)->Release(C_TYPEINFO(obj));
                }
-               obj->i.dispatch->lpVtbl->Release(obj->i.dispatch);
-               obj->referenced--;
+               if(C_HASENUM(obj))
+               {
+                       C_ENUMVARIANT_VT(obj)->Release(C_ENUMVARIANT(obj));
+               }
+               C_DISPATCH_VT(obj)->Release(C_DISPATCH(obj));
+               C_RELEASE(obj);
        }
 
-       return obj->referenced;
+       return obj->refcount;
 }
 
-PHPAPI HRESULT php_COM_addref(i_dispatch *obj)
+PHPAPI HRESULT php_COM_addref(comval *obj)
 {
-       if(obj->referenced)
+       if(C_ISREFD(obj))
        {
-               obj->referenced++;
+               C_ADDREF(obj);
        }
 
-       return obj->referenced;
+       return obj->refcount;
 }
 
-PHPAPI HRESULT php_COM_set(i_dispatch *obj, IDispatch FAR* pDisp, int cleanup)
+PHPAPI HRESULT php_COM_set(comval *obj, IDispatch FAR* pDisp, int cleanup)
 {
        HRESULT hr = 1;
+       DISPPARAMS dispparams;
+       VARIANT var_result;
+
+       C_DISPATCH(obj) = pDisp;
+       obj->refcount = 1;
+       C_HASTLIB(obj) = SUCCEEDED(C_DISPATCH_VT(obj)->GetTypeInfo(C_DISPATCH(obj), 0, LANG_NEUTRAL, &C_TYPEINFO(obj)));
+
+       dispparams.rgvarg = NULL;
+       dispparams.rgdispidNamedArgs = NULL;
+       dispparams.cArgs = 0;
+       dispparams.cNamedArgs = 0;
 
-       obj->i.dispatch = pDisp;
-       obj->referenced = 1;
-       obj->typelib = SUCCEEDED(obj->i.dispatch->lpVtbl->GetTypeInfo(obj->i.dispatch, 0, LANG_NEUTRAL, &obj->i.typeinfo));
+       if(C_HASENUM(obj) = SUCCEEDED(C_DISPATCH_VT(obj)->Invoke(C_DISPATCH(obj), DISPID_NEWENUM, &IID_NULL, LOCALE_SYSTEM_DEFAULT,
+                                                                       DISPATCH_METHOD|DISPATCH_PROPERTYGET, &dispparams, &var_result, NULL, NULL)))
+       {
+               if (V_VT(&var_result) == VT_UNKNOWN)
+               {
+                   C_HASENUM(obj) = SUCCEEDED(V_UNKNOWN(&var_result)->lpVtbl->QueryInterface(V_UNKNOWN(&var_result), &IID_IEnumVARIANT,
+                                                                       (void**)&C_ENUMVARIANT(obj)));
+               }
+               else if (V_VT(&var_result) == VT_DISPATCH)
+               {
+                   C_HASENUM(obj) = SUCCEEDED(V_DISPATCH(&var_result)->lpVtbl->QueryInterface(V_DISPATCH(&var_result), &IID_IEnumVARIANT,
+                                                                       (void**)&C_ENUMVARIANT(obj)));
+               }
+
+       }
 
        if(!cleanup)
        {
-               hr = obj->i.dispatch->lpVtbl->AddRef(obj->i.dispatch);
+               hr = C_DISPATCH_VT(obj)->AddRef(C_DISPATCH(obj));
        }
 
        return hr;
 }
 
-PHPAPI HRESULT php_COM_clone(i_dispatch *obj, i_dispatch *clone, int cleanup)
+PHPAPI HRESULT php_COM_clone(comval *obj, comval *clone, int cleanup)
 {
        HRESULT hr;
 
-       obj->typelib = clone->typelib;
-       obj->i.dispatch = clone->i.dispatch;
-       obj->i.typeinfo = clone->i.typeinfo;
+       C_HASTLIB(obj) = C_HASTLIB(clone);
+       C_HASENUM(obj) = C_HASENUM(obj);
+       C_DISPATCH(obj) = C_DISPATCH(clone);
+       C_TYPEINFO(obj) = C_TYPEINFO(clone);
 
-       if(cleanup || !obj->referenced)
+       if(cleanup || !C_ISREFD(obj))
        {
-               obj->referenced = clone->referenced;
-               clone->referenced = 0;
+               obj->refcount = clone->refcount;
+               C_ISREFD(clone) = FALSE;
        }
        else
        {
-               if(obj->typelib)
+               if(C_HASTLIB(obj))
+               {
+                       C_TYPEINFO_VT(obj)->AddRef(C_TYPEINFO(obj));
+               }
+               if(C_HASENUM(obj))
                {
-                       obj->i.typeinfo->lpVtbl->AddRef(obj->i.typeinfo);
+                       C_ENUMVARIANT_VT(obj)->AddRef(C_ENUMVARIANT(obj));
                }
-               hr = obj->i.dispatch->lpVtbl->AddRef(obj->i.dispatch);
-               obj->referenced = 1;
+               hr = C_DISPATCH_VT(obj)->AddRef(C_DISPATCH(obj));
+               obj->refcount = 1;
        }
 
        return hr;
@@ -282,8 +316,8 @@ static char *php_string_from_clsid(const CLSID *clsid)
 
 static void php_idispatch_destructor(zend_rsrc_list_entry *rsrc)
 {
-       i_dispatch *obj = (i_dispatch *)rsrc->ptr;
-       while(obj->referenced)
+       comval *obj = (comval *)rsrc->ptr;
+       while(C_ISREFD(obj))
        {
                php_COM_release(obj);
        }
@@ -330,7 +364,7 @@ static PHP_INI_MH(OnTypelibFileChange)
                        continue;
                }
                typelib_name = php_strtok_r(typelib_name_buffer, "\r\n", &strtok_buf); /* get rid of newlines */
-               if (typelib_name == NULL)
+               if(typelib_name == NULL)
                {
                        continue;
                }
@@ -345,12 +379,12 @@ static PHP_INI_MH(OnTypelibFileChange)
                }
 
                /* Remove leading/training white spaces on search_string */
-               while (isspace(*typelib_name)) /* Ends on '\0' in worst case */
+               while(isspace(*typelib_name)) /* Ends on '\0' in worst case */
                {
                        typelib_name ++;
                }
                ptr = typelib_name + strlen(typelib_name) - 1;
-               while ((ptr != typelib_name) && isspace(*ptr))
+               while((ptr != typelib_name) && isspace(*ptr))
                {
                        *ptr = '\0';
                        ptr--;
@@ -400,7 +434,7 @@ PHP_FUNCTION(com_load)
        CLSID clsid;
        HRESULT hr;
        OLECHAR *ProgID;
-       i_dispatch *obj;
+       comval *obj;
        char *error_message;
        char *clsid_str;
        int mode = CONST_PERSISTENT;
@@ -408,7 +442,7 @@ PHP_FUNCTION(com_load)
 
 
        codepage = CP_ACP;
-       
+
        switch(ZEND_NUM_ARGS())
        {
                case 1:
@@ -431,7 +465,7 @@ PHP_FUNCTION(com_load)
 
                        convert_to_string_ex(&typelib);
                        convert_to_long_ex(&code_page);
-                       codepage = code_page->value.lval;
+                       codepage = Z_LVAL_P(code_page);
 
                        break;
 
@@ -441,7 +475,7 @@ PHP_FUNCTION(com_load)
 
        if(server_name != NULL)
        {
-               if(server_name->type == IS_NULL)
+               if(Z_TYPE_P(server_name) == IS_NULL)
                {
                        server_name = NULL;
                }
@@ -460,73 +494,103 @@ PHP_FUNCTION(com_load)
        }
 
        convert_to_string_ex(&module_name);
-       ProgID = php_char_to_OLECHAR(module_name->value.str.val, module_name->value.str.len, codepage);
-       hr=CLSIDFromProgID(ProgID, &clsid);
-       efree(ProgID);
+       ProgID = php_char_to_OLECHAR(Z_STRVAL_P(module_name), Z_STRLEN_P(module_name), codepage);
+       obj = (comval *) emalloc(sizeof(comval));
 
        /* obtain CLSID */
-       if(FAILED(hr))
+       if(FAILED(CLSIDFromProgID(ProgID, &clsid)))
        {
-               error_message = php_COM_error_message(hr);  
-               php_error(E_WARNING,"Invalid ProgID:  %s\n", error_message);
-               LocalFree(error_message);
-               RETURN_FALSE;
-       }
+               /* Perhaps this is a Moniker? */
+               IBindCtx *pBindCtx;
+               IMoniker *pMoniker;
+               ULONG ulEaten;
 
-       obj = (i_dispatch *) emalloc(sizeof(i_dispatch));
+               /* TODO: if(server_name) */
 
-       /* obtain IDispatch */
-       if(!server_name)
-       {
-               hr = CoCreateInstance(&clsid, NULL, CLSCTX_SERVER, &IID_IDispatch, (LPVOID *) &(obj->i.dispatch));
+               if(!server_name)
+               {
+                       if(SUCCEEDED(hr = CreateBindCtx(0, &pBindCtx)))
+                       {
+                               if(SUCCEEDED(hr = MkParseDisplayName(pBindCtx, ProgID, &ulEaten, &pMoniker)))
+                               {
+                                       hr = pMoniker->lpVtbl->BindToObject(pMoniker, pBindCtx, NULL, &IID_IDispatch, (LPVOID *) &C_DISPATCH(obj));
+                                       pMoniker->lpVtbl->Release(pMoniker);
+                               }
+                               pBindCtx->lpVtbl->Release(pBindCtx);
+                       }
+               }
+               else
+               {
+                       hr = MK_E_SYNTAX;
+               }
+               
+               efree(ProgID);
+               
+               if(FAILED(hr))
+               {
+                       efree(obj);
+                       error_message = php_COM_error_message(hr);  
+                       php_error(E_WARNING,"Invalid ProgID or Moniker:  %s\n", error_message);
+                       LocalFree(error_message);
+                       RETURN_FALSE;
+               }
        }
        else
        {
-               COSERVERINFO server_info;
-               MULTI_QI pResults;
-
-               server_info.dwReserved1=0;
-               server_info.dwReserved2=0;
-               server_info.pwszName = php_char_to_OLECHAR(server_name->value.str.val, server_name->value.str.len, codepage);
-               server_info.pAuthInfo=NULL;
+               efree(ProgID);
+               /* obtain IDispatch */
+               if(!server_name)
+               {
+                       hr = CoCreateInstance(&clsid, NULL, CLSCTX_SERVER, &IID_IDispatch, (LPVOID *) &C_DISPATCH(obj));
+               }
+               else
+               {
+                       COSERVERINFO server_info;
+                       MULTI_QI pResults;
+
+                       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.pAuthInfo=NULL;
+
+                       pResults.pIID = &IID_IDispatch;
+                       pResults.pItf = NULL;
+                       pResults.hr = S_OK;
+                       hr=CoCreateInstanceEx(&clsid, NULL, CLSCTX_SERVER, &server_info, 1, &pResults);
+                       if(SUCCEEDED(hr))
+                       {
+                               hr = pResults.hr;
+                               C_DISPATCH(obj) = (IDispatch *) pResults.pItf;
+                       }
+                       efree(server_info.pwszName);
+               }
 
-               pResults.pIID = &IID_IDispatch;
-               pResults.pItf = NULL;
-               pResults.hr = S_OK;
-               hr=CoCreateInstanceEx(&clsid, NULL, CLSCTX_SERVER, &server_info, 1, &pResults);
-               if(SUCCEEDED(hr))
+               if(FAILED(hr))
                {
-                       hr = pResults.hr;
-                       obj->i.dispatch = (IDispatch *) pResults.pItf;
+                       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);
+                       LocalFree(error_message);
+                       efree(clsid_str);
+                       efree(obj);
+                       RETURN_FALSE;
                }
-               efree(server_info.pwszName);
        }
 
-       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);
-               LocalFree(error_message);
-               efree(clsid_str);
-               efree(obj);
-               RETURN_FALSE;
-       }
+       php_COM_set(obj, C_DISPATCH(obj), TRUE);
 
-       php_COM_set(obj, obj->i.dispatch, TRUE);
-       
        if(INI_INT("com.autoregister_casesensitive"))
        {
                mode |= CONST_CS;
        }
 
-       if(obj->typelib)
+       if(C_HASTLIB(obj))
        {
                if(INI_INT("com.autoregister_typelib"))
                {
                        unsigned int idx;
 
-                       if(obj->i.typeinfo->lpVtbl->GetContainingTypeLib(obj->i.typeinfo, &pTL, &idx) == S_OK)
+                       if(C_TYPEINFO_VT(obj)->GetContainingTypeLib(C_TYPEINFO(obj), &pTL, &idx) == S_OK)
                        {
                                php_COM_load_typelib(pTL, mode);
                                pTL->lpVtbl->Release(pTL);
@@ -539,9 +603,9 @@ PHP_FUNCTION(com_load)
                {
                        ITypeLib *pTL;
 
-                       if((pTL = php_COM_find_typelib(typelib->value.str.val, mode)) != NULL)
+                       if((pTL = php_COM_find_typelib(Z_STRVAL_P(typelib), mode)) != NULL)
                        {
-                               obj->typelib = SUCCEEDED(pTL->lpVtbl->GetTypeInfo(pTL, 0, &obj->i.typeinfo));
+                               C_HASTLIB(obj) = SUCCEEDED(pTL->lpVtbl->GetTypeInfo(pTL, 0, &C_TYPEINFO(obj)));
                                /* idx 0 should deliver the ITypeInfo for the IDispatch Interface */
                                if(INI_INT("com.autoregister_typelib"))
                                {
@@ -557,56 +621,166 @@ PHP_FUNCTION(com_load)
 /* }}} */
 
 
-int do_COM_invoke(i_dispatch *obj, pval *function_name, VARIANTARG *var_result, pval **arguments, int arg_count)
+int do_COM_invoke(comval *obj, pval *function_name, VARIANT *var_result, pval **arguments, int arg_count)
 {
        DISPID dispid;
        HRESULT hr;
        OLECHAR *funcname;
        char *error_message;
-       VARIANTARG *variant_args;
+       VARIANT *variant_args;
        int current_arg, current_variant;
        DISPPARAMS dispparams;
+       SAFEARRAY *pSA;
 
-       funcname = php_char_to_OLECHAR(function_name->value.str.val, function_name->value.str.len, codepage);
+       if(C_HASENUM(obj) && strstr(Z_STRVAL_P(function_name), "next"))
+       {
+               // Grab one argument off the stack, allocate enough
+               // VARIANTs
+               // Get the IEnumVariant interface and call ->Next();
+               SAFEARRAYBOUND rgsabound[1];
+               unsigned long count;
 
-       hr = php_COM_get_ids_of_names(obj, &funcname, &dispid);
+               switch(arg_count)
+               {
+                       case 0:
+                               count = 1;
+                               break;
 
-       if(FAILED(hr))
-       {
-               error_message = php_COM_error_message(hr);
-               php_error(E_WARNING,"Unable to lookup %s:  %s\n", function_name->value.str.val, error_message);
-               LocalFree(error_message);
-               efree(funcname);
-               return FAILURE;
-       }
+                       case 1:
+                               convert_to_long_ex(&arguments[0]);
+                               count = Z_LVAL_P(arguments[0]);
+                               break;
 
-       variant_args = (VARIANTARG *) emalloc(sizeof(VARIANTARG)*arg_count);
+                       default:
+                               /* TODO: complain about wrong arg count */
+                               php_error(E_WARNING,"Wrong argument count to IEnumVariant::Next()\n");
+
+                               return FAILURE;
+               }
+
+               rgsabound[0].lLbound = 0;
+               rgsabound[0].cElements = count;
+
+               if((pSA = SafeArrayCreate(VT_VARIANT, 1, rgsabound)) == NULL)
+               {
+                       VariantInit(var_result);
+                       return FAILURE;
+               }
+               else
+               {
+                       V_ARRAY(var_result) = pSA;
+                       V_VT(var_result) = VT_VARIANT|VT_ARRAY;
+               }
+
+               if(FAILED(hr = C_ENUMVARIANT_VT(obj)->Next(C_ENUMVARIANT(obj), count, pSA->pvData, &count)))
+               {
+                       char *error_message = php_COM_error_message(hr);
+                       php_error(E_WARNING,"IEnumVariant::Next() failed:  %s\n", error_message);
+                       efree(error_message);
+                       SafeArrayDestroy(pSA);
+                       VariantInit(var_result);
+                       return FAILURE;
+               }
+
+               if(count != rgsabound[0].cElements)
+               {
+                       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);
+                               efree(error_message);
+                               SafeArrayDestroy(pSA);
+                               VariantInit(var_result);
+                               return FAILURE;
+                       }
+               }
 
-       for(current_arg=0; current_arg<arg_count; current_arg++)
+               return SUCCESS;
+       }
+       else if(C_HASENUM(obj) && strstr(Z_STRVAL_P(function_name), "reset"))
        {
-               current_variant = arg_count - current_arg - 1;
-               php_pval_to_variant(arguments[current_arg], &variant_args[current_variant], codepage);
+               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);
+                       efree(error_message);
+                       return FAILURE;
+               }
+               return SUCCESS;
        }
+       else if(C_HASENUM(obj) && strstr(Z_STRVAL_P(function_name), "skip"))
+       {
+               unsigned long count;
 
-       dispparams.rgvarg = variant_args;
-       dispparams.rgdispidNamedArgs = NULL;
-       dispparams.cArgs = arg_count;
-       dispparams.cNamedArgs = 0;
+               switch(arg_count)
+               {
+                       case 0:
+                               count = 1;
+                               break;
 
-       hr = php_COM_invoke(obj, dispid, DISPATCH_METHOD|DISPATCH_PROPERTYGET, &dispparams, var_result);
+                       case 1:
+                               convert_to_long_ex(&arguments[0]);
+                               count = Z_LVAL_P(arguments[0]);
+                               break;
 
-       if(FAILED(hr))
+                       default:
+                               php_error(E_WARNING,"Wrong argument count to IEnumVariant::Skip()\n");
+                               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);
+                       efree(error_message);
+                       return FAILURE;
+               }
+               return SUCCESS;
+
+       }
+       else
        {
-               error_message = php_COM_error_message(hr);
-               php_error(E_WARNING,"Invoke() failed:  %s\n", error_message);
-               LocalFree(error_message);
-               efree(funcname);
+               funcname = php_char_to_OLECHAR(Z_STRVAL_P(function_name), Z_STRLEN_P(function_name), codepage);
+
+               hr = php_COM_get_ids_of_names(obj, &funcname, &dispid);
+
+               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);
+                       LocalFree(error_message);
+                       efree(funcname);
+                       return FAILURE;
+               }
+
+               variant_args = (VARIANT*) emalloc(sizeof(VARIANT)*arg_count);
+
+               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);
+               }
+
+               dispparams.rgvarg = variant_args;
+               dispparams.rgdispidNamedArgs = NULL;
+               dispparams.cArgs = arg_count;
+               dispparams.cNamedArgs = 0;
+
+               hr = php_COM_invoke(obj, dispid, DISPATCH_METHOD|DISPATCH_PROPERTYGET, &dispparams, var_result);
+
+               if(FAILED(hr))
+               {
+                       error_message = php_COM_error_message(hr);
+                       php_error(E_WARNING,"Invoke() failed:  %s\n", error_message);
+                       LocalFree(error_message);
+                       efree(funcname);
+                       efree(variant_args);
+                       return FAILURE;
+               }
+
                efree(variant_args);
-               return FAILURE;
+               efree(funcname);
        }
-
-       efree(variant_args);
-       efree(funcname);
        return SUCCESS;
 }
 
@@ -617,10 +791,10 @@ PHP_FUNCTION(com_invoke)
 {
        pval **arguments;
        pval *object, *function_name;
-       i_dispatch *obj;
+       comval *obj;
        int type;
        int arg_count = ZEND_NUM_ARGS();
-       VARIANTARG var_result;
+       VARIANT var_result;
 
        if(arg_count<2)
        {
@@ -637,10 +811,10 @@ PHP_FUNCTION(com_invoke)
 
        /* obtain IDispatch interface */
        convert_to_long(object);
-       obj = (i_dispatch *)zend_list_find(object->value.lval, &type);
+       obj = (comval *)zend_list_find(Z_LVAL_P(object), &type);
        if(!obj || (type!=le_idispatch))
        {
-               php_error(E_WARNING,"%d is not a COM object handler", function_name->value.str.val);
+               php_error(E_WARNING,"%d is not a COM object handler", Z_STRVAL_P(function_name));
                RETURN_FALSE;
        }
 
@@ -662,7 +836,7 @@ PHP_FUNCTION(com_invoke)
 PHP_FUNCTION(com_release)
 {
        pval *object;
-       i_dispatch *obj;
+       comval *obj;
        int type;
        int arg_count = ZEND_NUM_ARGS();
 
@@ -670,23 +844,22 @@ PHP_FUNCTION(com_release)
        {
                WRONG_PARAM_COUNT;
        }
-       
+
        if(getParameters(ht, 1, &object)==FAILURE)
        {
                RETURN_FALSE;
        }
 
        /* obtain IDispatch interface */
-       convert_to_long(object);
-       obj = (i_dispatch *)zend_list_find(object->value.lval, &type);
-       if(!obj || (type!=le_idispatch))
+       convert_to_long_ex(&object);
+       obj = (comval *)zend_list_find(Z_LVAL_P(object), &type);
+       if(!obj || (type != le_idispatch))
        {
                php_error(E_WARNING,"%d is not a COM object handler");
                RETURN_FALSE;
        }
 
-       return_value->type = IS_LONG;
-       return_value->value.lval = php_COM_release(obj);
+       RETURN_LONG(php_COM_release(obj))
 }
 /* }}} */
 
@@ -695,7 +868,7 @@ PHP_FUNCTION(com_release)
 PHP_FUNCTION(com_addref)
 {
        pval *object;
-       i_dispatch *obj;
+       comval *obj;
        int type;
        int arg_count = ZEND_NUM_ARGS();
 
@@ -703,34 +876,31 @@ PHP_FUNCTION(com_addref)
        {
                WRONG_PARAM_COUNT;
        }
-       
+
        if(getParameters(ht, 1, &object)==FAILURE)
        {
                RETURN_FALSE;
        }
 
        /* obtain IDispatch interface */
-       convert_to_long(object);
-       obj = (i_dispatch *)zend_list_find(object->value.lval, &type);
-       if(!obj || (type!=le_idispatch))
+       convert_to_long_ex(&object);
+       obj = (comval *)zend_list_find(Z_LVAL_P(object), &type);
+       if(!obj || (type != le_idispatch))
        {
                php_error(E_WARNING,"%d is not a COM object handler");
                RETURN_FALSE;
        }
 
-       return_value->type = IS_LONG;
-       return_value->value.lval = php_COM_addref(obj);
+       RETURN_LONG(php_COM_addref(obj));
 }
 /* }}} */
 
-static int do_COM_offget(VARIANT *result, i_dispatch *array, pval *property, int cleanup)
+static int do_COM_offget(VARIANT *result, comval *array, pval *property, int cleanup)
 {
        pval function_name;
        int retval;
 
-       function_name.value.str.val = "Item";
-       function_name.value.str.len = 4;
-       function_name.type = IS_STRING;
+       ZVAL_STRINGL(&function_name, "Item", 4, 0);
        retval = do_COM_invoke(array, &function_name, result, &property, 1);
        if(cleanup)
        {
@@ -741,7 +911,7 @@ static int do_COM_offget(VARIANT *result, i_dispatch *array, pval *property, int
        return retval;
 }
 
-static int do_COM_propget(VARIANTARG *var_result, i_dispatch *obj, pval *arg_property, int cleanup)
+static int do_COM_propget(VARIANT *var_result, comval *obj, pval *arg_property, int cleanup)
 {
        DISPID dispid;
        HRESULT hr;
@@ -751,14 +921,14 @@ static int do_COM_propget(VARIANTARG *var_result, i_dispatch *obj, pval *arg_pro
 
 
        /* obtain property handler */
-       propname = php_char_to_OLECHAR(arg_property->value.str.val, arg_property->value.str.len, codepage);
+       propname = php_char_to_OLECHAR(Z_STRVAL_P(arg_property), Z_STRLEN_P(arg_property), codepage);
 
        hr = php_COM_get_ids_of_names(obj, &propname, &dispid);
 
        if(FAILED(hr))
        {
                error_message = php_COM_error_message(hr);
-               php_error(E_WARNING,"Unable to lookup %s:  %s\n", arg_property->value.str.val, error_message);
+               php_error(E_WARNING,"Unable to lookup %s:  %s\n", Z_STRVAL_P(arg_property), error_message);
                LocalFree(error_message);
                efree(propname);
                if(cleanup)
@@ -795,7 +965,7 @@ static int do_COM_propget(VARIANTARG *var_result, i_dispatch *obj, pval *arg_pro
 }
 
 
-static void do_COM_propput(pval *return_value, i_dispatch *obj, pval *arg_property, pval *value)
+static void do_COM_propput(pval *return_value, comval *obj, pval *arg_property, pval *value)
 {
        DISPID dispid;
        HRESULT hr;
@@ -803,21 +973,21 @@ static void do_COM_propput(pval *return_value, i_dispatch *obj, pval *arg_proper
        char *error_message;
        VARIANT *var_result;
        DISPPARAMS dispparams;
-       VARIANTARG new_value;
+       VARIANT new_value;
        DISPID mydispid = DISPID_PROPERTYPUT;
 
 
        var_result = emalloc(sizeof(VARIANT));
 
        /* obtain property handler */
-       propname = php_char_to_OLECHAR(arg_property->value.str.val, arg_property->value.str.len, codepage);
+       propname = php_char_to_OLECHAR(Z_STRVAL_P(arg_property), Z_STRLEN_P(arg_property), codepage);
 
        hr = php_COM_get_ids_of_names(obj, &propname, &dispid);
 
        if(FAILED(hr))
        {
                error_message = php_COM_error_message(hr);
-               php_error(E_WARNING,"Unable to lookup %s:  %s\n", arg_property->value.str.val, error_message);
+               php_error(E_WARNING,"Unable to lookup %s:  %s\n", Z_STRVAL_P(arg_property), error_message);
                LocalFree(error_message);
                efree(propname);
                RETURN_FALSE;
@@ -866,8 +1036,8 @@ PHP_FUNCTION(com_propget)
 {
        pval *arg_idispatch, *arg_property;
        int type;
-       i_dispatch *obj;
-       VARIANTARG var_result;
+       comval *obj;
+       VARIANT var_result;
 
        if(ZEND_NUM_ARGS()!=2 || getParameters(ht, 2, &arg_idispatch, &arg_property)==FAILURE)
        {
@@ -876,10 +1046,10 @@ PHP_FUNCTION(com_propget)
 
        /* obtain IDispatch interface */
        convert_to_long(arg_idispatch);
-       obj = (i_dispatch *)zend_list_find(arg_idispatch->value.lval,&type);
-       if(!obj || (type!=le_idispatch))
+       obj = (comval *)zend_list_find(Z_LVAL_P(arg_idispatch), &type);
+       if(!obj || (type != le_idispatch))
        {
-               php_error(E_WARNING,"%d is not a COM object handler", arg_idispatch->value.lval);
+               php_error(E_WARNING,"%d is not a COM object handler", Z_LVAL_P(arg_idispatch));
        }
        convert_to_string_ex(&arg_property);
 
@@ -898,20 +1068,20 @@ PHP_FUNCTION(com_propput)
 {
        pval *arg_idispatch, *arg_property, *arg_value;
        int type;
-       i_dispatch *obj;
+       comval *obj;
 
        if(ZEND_NUM_ARGS()!=3 || getParameters(ht, 3, &arg_idispatch, &arg_property, &arg_value)==FAILURE)
        {
                WRONG_PARAM_COUNT;
        }
 
-       /* obtain i_dispatch interface */
+       /* obtain comval interface */
        convert_to_long(arg_idispatch);
-       /* obtain i_dispatch interface */
-       obj = (i_dispatch *)zend_list_find(arg_idispatch->value.lval,&type);
-       if(!obj || (type!=le_idispatch))
+       /* obtain comval interface */
+       obj = (comval *)zend_list_find(Z_LVAL_P(arg_idispatch), &type);
+       if(!obj || (type != le_idispatch))
        {
-               php_error(E_WARNING,"%d is not a COM object handler", arg_idispatch->value.lval);
+               php_error(E_WARNING,"%d is not a COM object handler", Z_LVAL_P(arg_idispatch));
        }
        convert_to_string_ex(&arg_property);
 
@@ -944,15 +1114,15 @@ PHP_FUNCTION(com_load_typelib)
        }
 
        convert_to_string_ex(&arg_typelib);
-       pTL = php_COM_find_typelib(arg_typelib->value.str.val, mode);
+       pTL = php_COM_find_typelib(Z_STRVAL_P(arg_typelib), mode);
        if(php_COM_load_typelib(pTL, mode) == SUCCESS)
        {
                pTL->lpVtbl->Release(pTL);
-               RETVAL_TRUE;
+               RETURN_TRUE;
        }
        else
        {
-               RETVAL_FALSE;
+               RETURN_FALSE;
        }
 }
 /* }}} */
@@ -965,26 +1135,27 @@ PHPAPI pval php_COM_get_property_handler(zend_property_reference *property_refer
        pval **idispatch_handle;
        pval *object = property_reference->object;
        int type;
-       i_dispatch *obj, *obj_prop;
+       comval *obj, *obj_prop;
        VARIANT *var_result;
 
-       INIT_ZVAL(return_value);        
+       INIT_ZVAL(return_value);    
        ZVAL_NULL(&return_value);
 
        /* fetch the IDispatch interface */
        zend_hash_index_find(object->value.obj.properties, 0, (void **) &idispatch_handle);
-       obj = (i_dispatch *) zend_list_find((*idispatch_handle)->value.lval, &type);
-       if(!obj || (type!=le_idispatch))
+       obj = (comval *) zend_list_find(Z_LVAL_P(*idispatch_handle), &type);
+       if(!obj || (type != le_idispatch))
        {
                return return_value;
        }
 
-       obj_prop = (i_dispatch *) emalloc(sizeof(i_dispatch));
+       obj_prop = (comval *) emalloc(sizeof(comval));
        var_result = (VARIANT *) emalloc(sizeof(VARIANT));
-       
+
        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:
@@ -1030,27 +1201,27 @@ PHPAPI pval php_COM_get_property_handler(zend_property_reference *property_refer
                                                ZVAL_ADDREF(&return_value);
                                        }
 
-                                       efree(var_result);                              
-                               
+                                       efree(var_result);              
+
                                        return return_value;
                                }
                                break;
                }
 
-               if(var_result->vt == VT_DISPATCH)
+               if(V_VT(var_result) == VT_DISPATCH)
                {
                        pval *handle;
 
-                       if(var_result->pdispVal == NULL)
+                       if(V_DISPATCH(var_result) == NULL)
                        {
-                                       efree(var_result);
-                                       efree(obj_prop);
-                                       return return_value;
+                               efree(var_result);
+                               efree(obj_prop);
+                               return return_value;
                        }
 
                        obj = obj_prop;
-                       
-                       php_COM_set(obj_prop, var_result->pdispVal, TRUE);
+
+                       php_COM_set(obj_prop, V_DISPATCH(var_result), TRUE);
 
                        return_value.type = IS_OBJECT;
                        return_value.value.obj.ce = &com_class_entry;
@@ -1073,7 +1244,7 @@ PHPAPI pval php_COM_get_property_handler(zend_property_reference *property_refer
 
                pval_destructor(&overloaded_property->element);
        }
-       efree(var_result);                              
+       efree(var_result);              
 
        return return_value;
 }
@@ -1085,20 +1256,20 @@ PHPAPI int php_COM_set_property_handler(zend_property_reference *property_refere
        zend_llist_element *element;
        pval **idispatch_handle;
        pval *object = property_reference->object;
-       i_dispatch *obj;
+       comval *obj;
        int type;
-       VARIANTARG var_result;
+       VARIANT var_result;
 
 
        /* fetch the IDispatch interface */
        zend_hash_index_find(object->value.obj.properties, 0, (void **) &idispatch_handle);
-       obj = (i_dispatch *)zend_list_find((*idispatch_handle)->value.lval,&type);
-       if(!obj || (type!=le_idispatch))
+       obj = (comval *)zend_list_find(Z_LVAL_P(*idispatch_handle), &type);
+       if(!obj || (type != le_idispatch))
        {
                return FAILURE;
        }
        var_result.vt = VT_DISPATCH;
-       var_result.pdispVal = obj->i.dispatch;
+       var_result.pdispVal = C_DISPATCH(obj);
 
        for(element=property_reference->elements_list->head; element && element!=property_reference->elements_list->tail; element=element->next)
        {
@@ -1108,7 +1279,7 @@ PHPAPI int php_COM_set_property_handler(zend_property_reference *property_refere
                        case OE_IS_ARRAY:
                                break;
                        case OE_IS_OBJECT:
-                               if(var_result.vt != VT_DISPATCH)
+                               if(V_VT(&var_result) != VT_DISPATCH)
                                {
                                        return FAILURE;
                                }
@@ -1125,13 +1296,13 @@ PHPAPI int php_COM_set_property_handler(zend_property_reference *property_refere
                pval_destructor(&overloaded_property->element);
        }
 
-       if(var_result.vt != VT_DISPATCH)
+       if(V_VT(&var_result) != VT_DISPATCH)
        {
                return FAILURE;
        }
-       obj = (i_dispatch *) emalloc(sizeof(i_dispatch));
-       obj->typelib = FALSE;
-       obj->i.dispatch = var_result.pdispVal;
+       obj = (comval *) emalloc(sizeof(comval));
+       C_HASTLIB(obj) = FALSE;
+       C_DISPATCH(obj) = V_DISPATCH(&var_result);
 
        overloaded_property = (zend_overloaded_element *) element->data;
        do_COM_propput(&result, obj, &overloaded_property->element, value);
@@ -1146,7 +1317,7 @@ PHPAPI void php_COM_call_function_handler(INTERNAL_FUNCTION_PARAMETERS, zend_pro
        pval property, **handle;
        pval *object = property_reference->object;
        zend_overloaded_element *function_name = (zend_overloaded_element *) property_reference->elements_list->tail->data;
-       i_dispatch *obj;
+       comval *obj;
        int type;
 
        if(zend_llist_count(property_reference->elements_list)==1
@@ -1181,7 +1352,7 @@ PHPAPI void php_COM_call_function_handler(INTERNAL_FUNCTION_PARAMETERS, zend_pro
                return;
        }
        zend_hash_index_find(property.value.obj.properties, 0, (void **) &handle);
-       obj = (i_dispatch *)zend_list_find((*handle)->value.lval,&type);
+       obj = (comval *)zend_list_find((*handle)->value.lval,&type);
 
        if(!obj || (type!=le_idispatch))
        {
@@ -1191,16 +1362,14 @@ PHPAPI void php_COM_call_function_handler(INTERNAL_FUNCTION_PARAMETERS, zend_pro
        }
 
        if(zend_llist_count(property_reference->elements_list)==1
-          && !strcmp(function_name->element.value.str.val, "release"))
+          && !strcmp(Z_STRVAL_P(&function_name->element), "release"))
        {
-               return_value->type = IS_LONG;
-               return_value->value.lval = php_COM_release(obj);
+               RETVAL_LONG(php_COM_release(obj));
        }
        else if(zend_llist_count(property_reference->elements_list)==1
-          && !strcmp(function_name->element.value.str.val, "addref"))
+                       && !strcmp(Z_STRVAL_P(&function_name->element), "addref"))
        {
-               return_value->type = IS_LONG;
-               return_value->value.lval = php_COM_addref(obj);
+               RETVAL_LONG(php_COM_addref(obj));
        }
        else
        {
@@ -1209,8 +1378,8 @@ PHPAPI void php_COM_call_function_handler(INTERNAL_FUNCTION_PARAMETERS, zend_pro
                int arg_count = ZEND_NUM_ARGS();
 
                var_result = (VARIANT *) emalloc(sizeof(VARIANT));
-               
-               var_result->vt = VT_EMPTY;
+
+               VariantInit(var_result);
 
                arguments = (pval **) emalloc(sizeof(pval *)*arg_count);
                getParametersArray(ht, arg_count, arguments);
@@ -1219,8 +1388,10 @@ PHPAPI void php_COM_call_function_handler(INTERNAL_FUNCTION_PARAMETERS, zend_pro
                {
                        RETVAL_FALSE;
                }
-
-               php_variant_to_pval(var_result, return_value, 0, codepage);
+               else
+               {
+                       php_variant_to_pval(var_result, return_value, 0, codepage);
+               }
 
                efree(arguments);
                efree(var_result);
@@ -1328,12 +1499,12 @@ 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;
                        }
-                       if (ERROR_SUCCESS != RegQueryInfoKey(hkey, NULL, NULL, NULL, &SubKeys, &MaxSubKeyLength, NULL, NULL, NULL, NULL, NULL, NULL))
+                       if(ERROR_SUCCESS != RegQueryInfoKey(hkey, NULL, NULL, NULL, &SubKeys, &MaxSubKeyLength, NULL, NULL, NULL, NULL, NULL, NULL))
                        {
                                RegCloseKey(hkey);
                                return NULL;
@@ -1341,27 +1512,27 @@ static ITypeLib *php_COM_find_typelib(char *search_string, int mode)
                        MaxSubKeyLength++; /* \0 is not counted */
                        keyname = emalloc(MaxSubKeyLength);
                        libname = emalloc(strlen(search_string)+1);
-                       for (ii=0;ii<SubKeys;ii++)
+                       for(ii=0;ii<SubKeys;ii++)
                        {
-                               if (ERROR_SUCCESS != RegEnumKey(hkey, ii, keyname, MaxSubKeyLength))
+                               if(ERROR_SUCCESS != RegEnumKey(hkey, ii, keyname, MaxSubKeyLength))
                                {
                                        /* Failed - who cares */
                                        continue;
                                }
-                               if (ERROR_SUCCESS != RegOpenKey(hkey, keyname, &hsubkey))
+                               if(ERROR_SUCCESS != RegOpenKey(hkey, keyname, &hsubkey))
                                {
                                        /* Failed - who cares */
                                        continue;
                                }
-                               if (ERROR_SUCCESS != RegQueryInfoKey(hsubkey, NULL, NULL, NULL, &VersionCount, NULL, NULL, NULL, NULL, NULL, NULL, NULL))
+                               if(ERROR_SUCCESS != RegQueryInfoKey(hsubkey, NULL, NULL, NULL, &VersionCount, NULL, NULL, NULL, NULL, NULL, NULL, NULL))
                                {
                                        /* Failed - who cares */
                                        RegCloseKey(hsubkey);
                                        continue;
                                }
-                               for (jj=0;jj<VersionCount;jj++)
+                               for(jj=0;jj<VersionCount;jj++)
                                {
-                                       if (ERROR_SUCCESS != RegEnumKey(hsubkey, jj, version, sizeof(version)))
+                                       if(ERROR_SUCCESS != RegEnumKey(hsubkey, jj, version, sizeof(version)))
                                        {
                                                /* Failed - who cares */
                                                continue;
@@ -1369,9 +1540,9 @@ static ITypeLib *php_COM_find_typelib(char *search_string, int mode)
                                        /* OK we just need to retrieve the default */
                                        /* value for this key and see if it matches */
                                        libnamelen = strlen(search_string)+1;
-                                       if (ERROR_SUCCESS == RegQueryValue(hsubkey, version, libname, &libnamelen))
+                                       if(ERROR_SUCCESS == RegQueryValue(hsubkey, version, libname, &libnamelen))
                                        {
-                                               if ((mode & CONST_CS) ? (strcmp(libname, search_string) == 0) : (stricmp(libname, search_string) == 0))
+                                               if((mode & CONST_CS) ? (strcmp(libname, search_string) == 0) : (stricmp(libname, search_string) == 0))
                                                {
                                                        char *str;
                                                        int major, minor;
@@ -1385,7 +1556,7 @@ static ITypeLib *php_COM_find_typelib(char *search_string, int mode)
                                                        /* Or just parse the version string and pass that in */
                                                        /* The version string seems like a more portable solution */
                                                        /* Given that there is a COM on Unix */
-                                                       if (2 != sscanf(version, "%d.%d", &major, &minor))
+                                                       if(2 != sscanf(version, "%d.%d", &major, &minor))
                                                        {
                                                                major = 1;
                                                                minor = 0;
@@ -1425,7 +1596,7 @@ static int php_COM_load_typelib(ITypeLib *TypeLib, int mode)
        int interfaces;
        ELS_FETCH();
 
-       if (NULL == TypeLib)
+       if(NULL == TypeLib)
        {
                return FAILURE;
        }
@@ -1487,6 +1658,35 @@ static int php_COM_load_typelib(ITypeLib *TypeLib, int mode)
        return SUCCESS;
 }
 
+/* {{{ proto bool com_isenum(com_module obj)
+   Grabs an IEnumVariant */
+PHP_FUNCTION(com_isenum)
+{
+       pval *object;
+       pval **idispatch_handle;
+       comval *obj;
+       int type;
+
+       if(ZEND_NUM_ARGS() != 1)
+       {
+               WRONG_PARAM_COUNT;
+       }
+
+       getParameters(ht, 1, &object);
+
+       /* obtain IDispatch interface */
+       zend_hash_index_find(object->value.obj.properties, 0, (void **) &idispatch_handle);
+       obj = (comval *) zend_list_find((*idispatch_handle)->value.lval, &type);
+       if(!obj || (type!=le_idispatch))
+       {
+               php_error(E_WARNING,"%s is not a COM object handler", "");
+               RETURN_FALSE;
+       }
+
+       RETURN_BOOL(C_HASENUM(obj));
+}
+/* }}} */
+
 void php_register_COM_class()
 {
        INIT_OVERLOADED_CLASS_ENTRY(com_class_entry, "COM", NULL,
index 6c08f26e64ac7531cd7ee699650703f540e71042..0679cd162b7b4d03070d05e4e09d098278b49c1d 100644 (file)
@@ -5,21 +5,38 @@
 
 #include "oleauto.h"
 
-typedef struct i_dispatch_ {
-       int typelib;
-       int referenced;
+typedef struct comval_ {
+       BOOL typelib;
+       BOOL enumeration;
+       int refcount;
        struct {
                IDispatch *dispatch;
                ITypeInfo *typeinfo;
+               IEnumVARIANT *enumvariant;
        } i;
-} i_dispatch;
-
-PHPAPI HRESULT php_COM_invoke(i_dispatch *obj, DISPID dispIdMember, WORD wFlags, DISPPARAMS FAR*  pDispParams, VARIANT FAR* pVarResult);
-PHPAPI HRESULT php_COM_get_ids_of_names(i_dispatch *obj, OLECHAR FAR* FAR* rgszNames, DISPID FAR* rgDispId);
-PHPAPI HRESULT php_COM_release(i_dispatch *obj);
-PHPAPI HRESULT php_COM_addref(i_dispatch *obj);
-PHPAPI HRESULT php_COM_set(i_dispatch *obj, IDispatch FAR* pDisp, int cleanup);
-PHPAPI HRESULT php_COM_clone(i_dispatch *obj, i_dispatch *clone, int cleanup);
+} comval;
+
+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);
+
+#define C_HASTLIB(x)   ((x)->typelib)
+#define C_HASENUM(x)   ((x)->enumeration)
+#define C_ISREFD(x)    ((x)->refcount)
+
+#define C_DISPATCH(x)  ((x)->i.dispatch)
+#define C_TYPEINFO(x)  ((x)->i.typeinfo)
+#define C_ENUMVARIANT(x)       ((x)->i.enumvariant)
+
+#define C_DISPATCH_VT(x)       (C_DISPATCH(x)->lpVtbl)
+#define C_TYPEINFO_VT(x)       (C_TYPEINFO(x)->lpVtbl)
+#define C_ENUMVARIANT_VT(x)    (C_ENUMVARIANT(x)->lpVtbl)
+
+#define C_ADDREF(x)    (++((x)->refcount))
+#define C_RELEASE(x)   (--((x)->refcount))
 
 #endif  /* PHP_WIN32 */
 
index a105fb2e1b6cca08ebc4379c39d62964cac6b679..d892fa71b56426e0471da1112725dc4a82f8b764 100644 (file)
@@ -40,15 +40,17 @@ PHPAPI void php_pval_to_variant(pval *pval_arg, VARIANT *var_arg, int codepage)
 {
        OLECHAR *unicode_str;
 
-       switch(pval_arg->type)
+       VariantInit(var_arg);
+       
+       switch(Z_TYPE_P(pval_arg))
        {
                case IS_NULL:
-                       var_arg->vt = VT_NULL;
+                       V_VT(var_arg) = VT_NULL;
                        break;
 
                case IS_BOOL:
-                       var_arg->vt = VT_BOOL;
-                       var_arg->boolVal = (short)pval_arg->value.lval;
+                       V_VT(var_arg) = VT_BOOL;
+                       V_BOOL(var_arg) = (short) Z_LVAL_P(pval_arg);
                        break;
 
                case IS_OBJECT:
@@ -59,30 +61,33 @@ PHPAPI void php_pval_to_variant(pval *pval_arg, VARIANT *var_arg, int codepage)
 
                                /* fetch the VARIANT structure */
                                zend_hash_index_find(pval_arg->value.obj.properties, 0, (void **) &var_handle);
-                               var_arg->pvarVal = (VARIANT FAR*) zend_list_find((*var_handle)->value.lval, &type);
-                               var_arg->vt = VT_VARIANT|VT_BYREF;
+
+                               V_VT(var_arg) = VT_VARIANT|VT_BYREF;
+                               V_VARIANTREF(var_arg) = (VARIANT FAR*) zend_list_find(Z_LVAL_P(*var_handle), &type);
                        }
                        else if(!strcmp(pval_arg->value.obj.ce->name, "COM"))
                        {
                                pval **idispatch_handle;
-                               i_dispatch *obj;
+                               comval *obj;
                                int type;
 
                                /* fetch the IDispatch interface */
                                zend_hash_index_find(pval_arg->value.obj.properties, 0, (void **) &idispatch_handle);
-                               obj = (i_dispatch *)zend_list_find((*idispatch_handle)->value.lval, &type);
-                               if(!obj || (type != php_COM_get_le_idispatch()) || !obj->referenced)
+                               obj = (comval *)zend_list_find(Z_LVAL_P(*idispatch_handle), &type);
+                               if(!obj || (type != php_COM_get_le_idispatch()) || !C_ISREFD(obj))
                                {
                                        VariantInit(var_arg);
                                }
                                else
                                {
-                                       var_arg->vt = VT_DISPATCH;
-                                       var_arg->pdispVal = obj->i.dispatch;
+                                       V_VT(var_arg) = VT_DISPATCH;
+                                       V_DISPATCH(var_arg) = C_DISPATCH(obj);
                                }
                        }
                        else
+                       {
                                VariantInit(var_arg);
+                       }
                        break;
 
                case IS_ARRAY:
@@ -99,19 +104,19 @@ PHPAPI void php_pval_to_variant(pval *pval_arg, VARIANT *var_arg, int codepage)
                        break;
 
                case IS_LONG:
-                       var_arg->vt = VT_I4;   /* assuming 32-bit platform */
-                       var_arg->lVal = pval_arg->value.lval;
+                       V_VT(var_arg) = VT_I4;   /* assuming 32-bit platform */
+                       V_I4(var_arg) = Z_LVAL_P(pval_arg);
                        break;
 
                case IS_DOUBLE:
-                       var_arg->vt = VT_R8;   /* assuming 64-bit double precision */
-                       var_arg->dblVal = pval_arg->value.dval;
+                       V_VT(var_arg) = VT_R8;   /* assuming 64-bit double precision */
+                       V_R8(var_arg) = Z_DVAL_P(pval_arg);
                        break;
 
                case IS_STRING:
-                       var_arg->vt = VT_BSTR;
-                       unicode_str = php_char_to_OLECHAR(pval_arg->value.str.val, pval_arg->value.str.len, codepage);
-                       var_arg->bstrVal = SysAllocString(unicode_str);
+                       V_VT(var_arg) = VT_BSTR;
+                       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);
        }
 }
@@ -120,48 +125,48 @@ PHPAPI void php_pval_to_variant_ex(pval *pval_arg, VARIANT *var_arg, pval *pval_
 {
        OLECHAR *unicode_str;
 
-       var_arg->vt = (short) pval_type->value.lval;
+       V_VT(var_arg) = (short)Z_LVAL_P(pval_type);
 
-       switch(var_arg->vt)
+       switch(V_VT(var_arg))
        {
                case VT_UI1:
                        convert_to_long_ex(&pval_arg);
-                       var_arg->bVal = (unsigned char)pval_arg->value.lval;
+                       V_UI1(var_arg) = (unsigned char)Z_LVAL_P(pval_arg);
                        break;
 
                case VT_I2:
                        convert_to_long_ex(&pval_arg);
-                       var_arg->iVal = (short)pval_arg->value.lval;
+                       V_I2(var_arg) = (short)Z_LVAL_P(pval_arg);
                        break;
 
                case VT_I4:
                        convert_to_long_ex(&pval_arg);
-                       var_arg->lVal = pval_arg->value.lval;
+                       V_I4(var_arg) = Z_LVAL_P(pval_arg);
                        break;
 
                case VT_R4:
                        convert_to_double_ex(&pval_arg);
-                       var_arg->fltVal = (float)pval_arg->value.dval;
+                       V_R4(var_arg) = (float)Z_DVAL_P(pval_arg);
                        break;
 
                case VT_R8:
                        convert_to_double_ex(&pval_arg);
-                       var_arg->dblVal = pval_arg->value.dval;
+                       V_R8(var_arg) = Z_DVAL_P(pval_arg);
                        break;
 
                case VT_BOOL:
                        convert_to_boolean_ex(&pval_arg);
-                       var_arg->boolVal = (short)pval_arg->value.lval;
+                       V_BOOL(var_arg) = (short)Z_LVAL_P(pval_arg);
                        break;
 
                case VT_ERROR:
                        convert_to_long_ex(&pval_arg);
-                       var_arg->scode = pval_arg->value.lval;
+                       V_ERROR(var_arg) = Z_LVAL_P(pval_arg);
                        break;
 
                case VT_CY:
                        convert_to_double_ex(&pval_arg);
-                       VarCyFromR8(pval_arg->value.dval, &(var_arg->cyVal));
+                       VarCyFromR8(Z_DVAL_P(pval_arg), &V_CY(var_arg));
                        break;
 
                case VT_DATE:
@@ -178,55 +183,44 @@ PHPAPI void php_pval_to_variant_ex(pval *pval_arg, VARIANT *var_arg, pval *pval_
                                wintime.wMinute = phptime->tm_min;
                                wintime.wSecond = phptime->tm_sec;
 
-                               SystemTimeToVariantTime(&wintime, &(var_arg->date));
+                               SystemTimeToVariantTime(&wintime, &V_DATE(var_arg));
                        }
 
                case VT_BSTR:
                        convert_to_string_ex(&pval_arg);
-                       unicode_str = php_char_to_OLECHAR(pval_arg->value.str.val, pval_arg->value.str.len, codepage);
-                       var_arg->bstrVal = SysAllocString(unicode_str);
+                       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(pval_arg->value.str.val, pval_arg->value.str.len, codepage);
-                       VarDecFromStr(unicode_str, LOCALE_SYSTEM_DEFAULT, 0, &(var_arg->decVal));
+                       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(pval_arg->value.str.val, pval_arg->value.str.len, codepage);
-                       VarDecFromStr(unicode_str, LOCALE_SYSTEM_DEFAULT, 0, var_arg->pdecVal);
+                       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:
                        php_pval_to_variant(pval_arg, var_arg, codepage);
-                       if(var_arg->vt != VT_DISPATCH)
+                       if(V_VT(var_arg) != VT_DISPATCH)
                        {
                                VariantInit(var_arg);
                        }
                        else
                        {
-                               HRESULT hr;
-
-                               hr = var_arg->pdispVal->lpVtbl->QueryInterface(var_arg->pdispVal, &IID_IUnknown, &(var_arg->punkVal));
-
-                               if(FAILED(hr))
-                               {
-                                       php_error(E_WARNING,"can't query IUnknown");
-                                       VariantInit(var_arg);
-                               }
-                               else
-                               {
-                                       var_arg->vt     = VT_UNKNOWN;
-                               }
+                               V_VT(var_arg) = VT_UNKNOWN;
+                               V_UNKNOWN(var_arg) = (IUnknown *) V_DISPATCH(var_arg);
                        }
                        break;
 
                case VT_DISPATCH:
                        php_pval_to_variant(pval_arg, var_arg, codepage);
-                       if(var_arg->vt != VT_DISPATCH)
+                       if(V_VT(var_arg) != VT_DISPATCH)
                        {
                                VariantInit(var_arg);
                        }
@@ -234,37 +228,37 @@ PHPAPI void php_pval_to_variant_ex(pval *pval_arg, VARIANT *var_arg, pval *pval_
 
                case VT_UI1|VT_BYREF:
                        convert_to_long(pval_arg);
-                       var_arg->pbVal = (unsigned char FAR*) &(pval_arg->value.lval);
+                       V_UI1REF(var_arg) = (unsigned char FAR*) &Z_LVAL_P(pval_arg);
                        break;
 
                case VT_I2|VT_BYREF:
                        convert_to_long(pval_arg);
-                       var_arg->piVal = (short FAR*) &(pval_arg->value.lval);
+                       V_I2REF(var_arg) = (short FAR*) &Z_LVAL_P(pval_arg);
                        break;
 
                case VT_I4|VT_BYREF:
                        convert_to_long(pval_arg);
-                       var_arg->plVal = (long FAR*) &(pval_arg->value.lval);
+                       V_I4REF(var_arg) = (long FAR*) &Z_LVAL_P(pval_arg);
                        break;
 
                case VT_R4|VT_BYREF:
                        convert_to_double(pval_arg);
-                       var_arg->pfltVal = (float FAR*) &(pval_arg->value.lval);
+                       V_R4REF(var_arg) = (float FAR*) &Z_LVAL_P(pval_arg);
                        break;
 
                case VT_R8|VT_BYREF:
                        convert_to_double(pval_arg);
-                       var_arg->pdblVal = (double FAR*) &(pval_arg->value.lval);
+                       V_R8REF(var_arg) = (double FAR*) &Z_LVAL_P(pval_arg);
                        break;
 
                case VT_BOOL|VT_BYREF:
                        convert_to_boolean(pval_arg);
-                       var_arg->pboolVal = (short FAR*) &(pval_arg->value.lval);
+                       V_BOOLREF(var_arg) = (short FAR*) &Z_LVAL_P(pval_arg);
                        break;
 
                case VT_ERROR|VT_BYREF:
                        convert_to_long(pval_arg);
-                       var_arg->pscode = (long FAR*) &(pval_arg->value.lval);
+                       V_ERRORREF(var_arg) = (long FAR*) &Z_LVAL_P(pval_arg);
                        break;
 
                case VT_CY|VT_BYREF:
@@ -291,51 +285,40 @@ PHPAPI void php_pval_to_variant_ex(pval *pval_arg, VARIANT *var_arg, pval *pval_
 
                case VT_BSTR|VT_BYREF:
                        convert_to_string(pval_arg);
-                       var_arg->pbstrVal = (BSTR FAR*) emalloc(sizeof(BSTR FAR*));
-                       unicode_str = php_char_to_OLECHAR(pval_arg->value.str.val, pval_arg->value.str.len, codepage);
-                       *(var_arg->pbstrVal) = SysAllocString(unicode_str);
+                       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:
                        php_pval_to_variant(pval_arg, var_arg, codepage);
-                       if(var_arg->vt != VT_DISPATCH)
+                       if(V_VT(var_arg) != VT_DISPATCH)
                        {
                                VariantInit(var_arg);
                        }
                        else
                        {
-                               HRESULT hr;
-
-                               hr = var_arg->pdispVal->lpVtbl->QueryInterface(var_arg->pdispVal, &IID_IUnknown, &(var_arg->punkVal));
-
-                               if(FAILED(hr))
-                               {
-                                       php_error(E_WARNING,"can't query IUnknown");
-                                       VariantInit(var_arg);
-                               }
-                               else
-                               {
-                                       var_arg->vt     = VT_UNKNOWN|VT_BYREF;
-                               }
+                               V_VT(var_arg) = VT_UNKNOWN|VT_BYREF;
+                               *V_UNKNOWNREF(var_arg) = (IUnknown *) *V_DISPATCHREF(var_arg);
                        }
                        break;
 
                case VT_DISPATCH|VT_BYREF:
                        php_pval_to_variant(pval_arg, var_arg, codepage);
-                       if(var_arg->vt != VT_DISPATCH)
+                       if(V_VT(var_arg) != VT_DISPATCH)
                        {
                                VariantInit(var_arg);
                        }
                        else
                        {
-                               var_arg->vt     |= VT_BYREF;
+                               V_VT(var_arg) |= VT_BYREF;
                        }
                        break;
 
                case VT_VARIANT|VT_BYREF:
                        php_pval_to_variant(pval_arg, var_arg, codepage);
-                       if(var_arg->vt != (VT_VARIANT | VT_BYREF))
+                       if(V_VT(var_arg) != (VT_VARIANT|VT_BYREF)) /* TODO: i don't believe that this works */
                        {
                                VariantInit(var_arg);
                        }
@@ -343,52 +326,52 @@ PHPAPI void php_pval_to_variant_ex(pval *pval_arg, VARIANT *var_arg, pval *pval_
 
                case VT_I1:
                        convert_to_long_ex(&pval_arg);
-                       var_arg->cVal = (char)pval_arg->value.lval;
+                       V_I1(var_arg) = (char)Z_LVAL_P(pval_arg);
                        break;
 
                case VT_UI2:
                        convert_to_long_ex(&pval_arg);
-                       var_arg->uiVal = (unsigned short)pval_arg->value.lval;
+                       V_UI2(var_arg) = (unsigned short)Z_LVAL_P(pval_arg);
                        break;
 
                case VT_UI4:
                        convert_to_long_ex(&pval_arg);
-                       var_arg->ulVal = (unsigned long)pval_arg->value.lval;
+                       V_UI4(var_arg) = (unsigned long)Z_LVAL_P(pval_arg);
                        break;
 
                case VT_INT:
                        convert_to_long_ex(&pval_arg);
-                       var_arg->intVal = (int)pval_arg->value.lval;
+                       V_INT(var_arg) = (int)Z_LVAL_P(pval_arg);
                        break;
 
                case VT_UINT:
                        convert_to_long_ex(&pval_arg);
-                       var_arg->uintVal = (unsigned int)pval_arg->value.lval;
+                       V_UINT(var_arg) = (unsigned int)Z_LVAL_P(pval_arg);
                        break;
 
                case VT_I1|VT_BYREF:
                        convert_to_long(pval_arg);
-                       var_arg->pcVal = (char FAR*) &pval_arg->value.lval;
+                       V_I1REF(var_arg) = (char FAR*) &Z_LVAL_P(pval_arg);
                        break;
 
                case VT_UI2|VT_BYREF:
                        convert_to_long(pval_arg);
-                       var_arg->puiVal = (unsigned short FAR*) &pval_arg->value.lval;
+                       V_UI2REF(var_arg) = (unsigned short FAR*) &Z_LVAL_P(pval_arg);
                        break;
 
                case VT_UI4|VT_BYREF:
                        convert_to_long(pval_arg);
-                       var_arg->pulVal = (unsigned long FAR*) &pval_arg->value.lval;
+                       V_UI4REF(var_arg) = (unsigned long FAR*) &Z_LVAL_P(pval_arg);
                        break;
 
                case VT_INT|VT_BYREF:
                        convert_to_long(pval_arg);
-                       var_arg->pintVal = (int FAR*) &pval_arg->value.lval;
+                       V_INTREF(var_arg) = (int FAR*) &Z_LVAL_P(pval_arg);
                        break;
 
                case VT_UINT|VT_BYREF:
                        convert_to_long(pval_arg);
-                       var_arg->puintVal = (unsigned int FAR*) &pval_arg->value.lval;
+                       V_UINTREF(var_arg) = (unsigned int FAR*) &Z_LVAL_P(pval_arg);
                        break;
 
                default:
@@ -406,7 +389,7 @@ PHPAPI int php_variant_to_pval(VARIANT *var_arg, pval *pval_arg, int persistent,
        INIT_PZVAL(pval_arg);
 
        /* Add SafeArray support */
-       if (var_arg->vt & VT_ARRAY)
+       if (V_ISARRAY(var_arg))
        {
                SAFEARRAY *array = V_ARRAY(var_arg);
                LONG indices[1];
@@ -416,6 +399,7 @@ PHPAPI int php_variant_to_pval(VARIANT *var_arg, pval *pval_arg, int persistent,
                UINT Dims;
                VARIANT vv;
                pval *element;
+               HRESULT hr;
 
                /* TODO: Add support for multi-dimensional SafeArrays */
                /* For now just validate that the SafeArray has one dimension */
@@ -434,7 +418,7 @@ PHPAPI int php_variant_to_pval(VARIANT *var_arg, pval *pval_arg, int persistent,
                        /* Mask off the array bit and assume */
                        /* what is left is the type of the array */
                        /* elements */
-                       vartype = var_arg->vt & ~VT_ARRAY;
+                       vartype = V_VT(var_arg) & ~VT_ARRAY;
                }
                SafeArrayGetUBound(array, 1, &ubound);
                SafeArrayGetLBound(array, 1, &lbound);
@@ -451,8 +435,16 @@ PHPAPI int php_variant_to_pval(VARIANT *var_arg, pval *pval_arg, int persistent,
                        /* Set up a variant to pass to a recursive call */
                        /* So that we do not need to have two copies */
                        /* of the code */
-                       vv.vt = vartype;
-                       if (S_OK != SafeArrayGetElement(array, indices, (VOID *) &(vv.lVal)))
+                       if (VT_VARIANT == vartype)
+                       {
+                               hr = SafeArrayGetElement(array, indices, (VOID *) &(vv));
+                       }
+                       else
+                       {
+                               V_VT(&vv) = vartype;
+                               hr = SafeArrayGetElement(array, indices, (VOID *) &(vv.lVal));
+                       }
+                       if (S_OK != hr)
             {
                                /* Failure to retieve an element probably means the array is sparse */
                                /* So leave the php array sparse too */
@@ -496,57 +488,57 @@ PHPAPI int php_variant_to_pval(VARIANT *var_arg, pval *pval_arg, int persistent,
                        break;
 
                case VT_UI1:
-                       if(var_arg->vt & VT_BYREF)
+                       if(V_ISBYREF(var_arg))
                        {
-                               ZVAL_LONG(pval_arg, (long)*(var_arg->pbVal));
+                               ZVAL_LONG(pval_arg, (long)*V_UI4REF(var_arg));
                        }
                        else
                        {
-                               ZVAL_LONG(pval_arg, (long)var_arg->pbVal);
+                               ZVAL_LONG(pval_arg, (long)V_UI4(var_arg));
                        }
                        break;
 
                case VT_I2:
-                       if(var_arg->vt & VT_BYREF)
+                       if(V_ISBYREF(var_arg))
                        {
-                               ZVAL_LONG(pval_arg, (long )*(var_arg->piVal));
+                               ZVAL_LONG(pval_arg, (long )*V_I2REF(var_arg));
                        }
                        else
                        {
-                               ZVAL_LONG(pval_arg, (long)var_arg->iVal);
+                               ZVAL_LONG(pval_arg, (long)V_I2(var_arg));
                        }
                        break;
 
                case VT_I4:
-                       if(var_arg->vt & VT_BYREF)
+                       if(V_ISBYREF(var_arg))
                        {
-                               ZVAL_LONG(pval_arg, *(var_arg->plVal));
+                               ZVAL_LONG(pval_arg, *V_I4REF(var_arg));
                        }
                        else
                        {
-                               ZVAL_LONG(pval_arg, var_arg->lVal);
+                               ZVAL_LONG(pval_arg, V_I4(var_arg));
                        }
                        break;
 
                case VT_R4:
-                       if(var_arg->vt & VT_BYREF)
+                       if(V_ISBYREF(var_arg))
                        {
-                               ZVAL_DOUBLE(pval_arg, (double)*(var_arg->pfltVal));
+                               ZVAL_DOUBLE(pval_arg, (double)*V_R4REF(var_arg));
                        }
                        else
                        {
-                               ZVAL_DOUBLE(pval_arg, (double)var_arg->fltVal);
+                               ZVAL_DOUBLE(pval_arg, (double)V_R4(var_arg));
                        }
                        break;
 
                case VT_R8:
-                       if(var_arg->vt & VT_BYREF)
+                       if(V_ISBYREF(var_arg))
                        {
-                               ZVAL_DOUBLE(pval_arg, *(var_arg->pdblVal));
+                               ZVAL_DOUBLE(pval_arg, *V_R8REF(var_arg));
                        }
                        else
                        {
-                               ZVAL_DOUBLE(pval_arg, var_arg->dblVal);
+                               ZVAL_DOUBLE(pval_arg, V_R8(var_arg));
                        }
                        break;
 
@@ -554,12 +546,11 @@ PHPAPI int php_variant_to_pval(VARIANT *var_arg, pval *pval_arg, int persistent,
                case VT_DECIMAL:
                        {
                                OLECHAR *unicode_str;
-                               switch(VarBstrFromDec(&var_arg->decVal, LOCALE_SYSTEM_DEFAULT, 0, &unicode_str))
+                               switch(VarBstrFromDec(&V_DECIMAL(var_arg), LOCALE_SYSTEM_DEFAULT, 0, &unicode_str))
                                {
                                        case S_OK:
-                                               
-                                               pval_arg->value.str.val = php_OLECHAR_to_char(unicode_str, &pval_arg->value.str.len, persistent, codepage);
-                                               pval_arg->type = IS_STRING;
+                                               Z_STRVAL_P(pval_arg) = php_OLECHAR_to_char(unicode_str, &Z_STRLEN_P(pval_arg), persistent, codepage);
+                                               Z_TYPE_P(pval_arg) = IS_STRING;
                                                break;
 
                                        default:
@@ -573,25 +564,25 @@ PHPAPI int php_variant_to_pval(VARIANT *var_arg, pval *pval_arg, int persistent,
 
                /* Currency */
                case VT_CY:
-                       if(var_arg->vt & VT_BYREF)
+                       if(V_ISBYREF(var_arg))
                        {
-                               VarR8FromCy(var_arg->cyVal, &(pval_arg->value.dval));
+                               VarR8FromCy(*V_CYREF(var_arg), &Z_DVAL_P(pval_arg));
                        }
                        else
                        {
-                               VarR8FromCy(*(var_arg->pcyVal), &(pval_arg->value.dval));
+                               VarR8FromCy(V_CY(var_arg), &Z_DVAL_P(pval_arg));
                        }
-                       pval_arg->type = IS_DOUBLE;
+                       Z_TYPE_P(pval_arg) = IS_DOUBLE;
                        break;
 
                case VT_BOOL:
-                       if(var_arg->vt & VT_BYREF)
+                       if(V_ISBYREF(var_arg))
                        {
-                               ZVAL_BOOL(pval_arg, *(var_arg->pboolVal));
+                               ZVAL_BOOL(pval_arg, *V_BOOLREF(var_arg));
                        }
                        else
                        {
-                               ZVAL_BOOL(pval_arg, var_arg->boolVal);
+                               ZVAL_BOOL(pval_arg, V_BOOL(var_arg));
                        }
                        break;
 
@@ -601,36 +592,37 @@ PHPAPI int php_variant_to_pval(VARIANT *var_arg, pval *pval_arg, int persistent,
                        break;
 
                case VT_VARIANT:
-                       php_variant_to_pval(var_arg->pvarVal, pval_arg, persistent, codepage);
+                       php_variant_to_pval(V_VARIANTREF(var_arg), pval_arg, persistent, codepage);
                        break;
 
                case VT_BSTR:
-                       if(pval_arg->is_ref == 0  || (var_arg->vt & VT_BYREF) != VT_BYREF)
+                       if(V_ISBYREF(var_arg))
                        {
-                               pval_arg->value.str.val = php_OLECHAR_to_char(var_arg->bstrVal, &pval_arg->value.str.len, persistent, codepage);
-                               SysFreeString(var_arg->bstrVal);
+                               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));
+                               efree(V_BSTRREF(var_arg));
                        }
                        else
                        {
-                               pval_arg->value.str.val = php_OLECHAR_to_char(*(var_arg->pbstrVal), &pval_arg->value.str.len, persistent, codepage);
-                               SysFreeString(*(var_arg->pbstrVal));
-                               efree(var_arg->pbstrVal);
+                               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));
                        }
 
-                       pval_arg->type = IS_STRING;
+                       Z_TYPE_P(pval_arg) = IS_STRING;
                        break;
 
-               case VT_DATE: {
+               case VT_DATE:
+                       {
                                SYSTEMTIME wintime;
                                struct tm phptime;
 
-                               if((var_arg->vt & VT_BYREF) != VT_BYREF)
+                               if(V_ISBYREF(var_arg))
                                {
-                                       VariantTimeToSystemTime(var_arg->date, &wintime);
+                                       VariantTimeToSystemTime(*V_DATEREF(var_arg), &wintime);
                                }
                                else
                                {
-                                       VariantTimeToSystemTime(*(var_arg->pdate), &wintime);
+                                       VariantTimeToSystemTime(V_DATE(var_arg), &wintime);
                                }
 
                                phptime.tm_year  = wintime.wYear - 1900;
@@ -647,15 +639,15 @@ PHPAPI int php_variant_to_pval(VARIANT *var_arg, pval *pval_arg, int persistent,
                        break;
 
                case VT_UNKNOWN:
-                       if(var_arg->punkVal == NULL)
+                       if(V_UNKNOWN(var_arg) == NULL)
                        {
-                               var_arg->pdispVal = NULL;
+                               V_DISPATCH(var_arg) = NULL;
                        }
                        else
                        {
                                HRESULT hr;
 
-                               hr = var_arg->punkVal->lpVtbl->QueryInterface(var_arg->punkVal, &IID_IDispatch, &(var_arg->pdispVal));
+                               hr = V_UNKNOWN(var_arg)->lpVtbl->QueryInterface(var_arg->punkVal, &IID_IDispatch, &V_DISPATCH(var_arg));
 
                                if(FAILED(hr))
                                {
@@ -665,26 +657,26 @@ PHPAPI int php_variant_to_pval(VARIANT *var_arg, pval *pval_arg, int persistent,
                                        php_error(E_WARNING,"Unable to obtain IDispatch interface:  %s", error_message);
                                        LocalFree(error_message);
 
-                                       var_arg->pdispVal = NULL;
+                                       V_DISPATCH(var_arg) = NULL;
                                }
                        }
                        /* break missing intentionaly */
                case VT_DISPATCH:
                        {
                                pval *handle;
-                               i_dispatch *obj;
+                               comval *obj;
 
-                               if(var_arg->pdispVal == NULL)
+                               if(V_DISPATCH(var_arg) == NULL)
                                {
                                        ret = FAILURE;
                                        ZVAL_NULL(pval_arg);
                                }
                                else
                                {
-                                       obj = emalloc(sizeof(i_dispatch));
-                                       php_COM_set(obj, var_arg->pdispVal, TRUE);
+                                       obj = emalloc(sizeof(comval));
+                                       php_COM_set(obj, V_DISPATCH(var_arg), TRUE);
 
-                                       pval_arg->type = IS_OBJECT;
+                                       Z_TYPE_P(pval_arg) = IS_OBJECT;
                                        pval_arg->value.obj.ce = &com_class_entry;
                                        pval_arg->value.obj.properties = (HashTable *) emalloc(sizeof(HashTable));
                                        zend_hash_init(pval_arg->value.obj.properties, 0, NULL, ZVAL_PTR_DTOR, 0);
@@ -700,62 +692,62 @@ PHPAPI int php_variant_to_pval(VARIANT *var_arg, pval *pval_arg, int persistent,
                        break;
 
                case VT_I1:
-                       if(var_arg->vt & VT_BYREF)
+                       if(V_ISBYREF(var_arg))
                        {
-                               ZVAL_LONG(pval_arg, (long)*(var_arg->pcVal));
+                               ZVAL_LONG(pval_arg, (long)*V_I1REF(var_arg));
                        }
                        else
                        {
-                               ZVAL_LONG(pval_arg, (long)var_arg->cVal);
+                               ZVAL_LONG(pval_arg, (long)V_I1(var_arg));
                        }
                        break;
 
                case VT_UI2:
-                       if(var_arg->vt & VT_BYREF)
+                       if(V_ISBYREF(var_arg))
                        {
-                               ZVAL_LONG(pval_arg, (long)*(var_arg->puiVal));
+                               ZVAL_LONG(pval_arg, (long)*V_UI2REF(var_arg));
                        }
                        else
                        {
-                               ZVAL_LONG(pval_arg, (long)var_arg->uiVal);
+                               ZVAL_LONG(pval_arg, (long)V_UI2(var_arg));
                        }
                        break;
 
                case VT_UI4:
-                       if(var_arg->vt & VT_BYREF)
+                       if(V_ISBYREF(var_arg))
                        {
-                               ZVAL_LONG(pval_arg, (long)*(var_arg->pulVal));
+                               ZVAL_LONG(pval_arg, (long)*V_UI4REF(var_arg));
                        }
                        else
                        {
-                               ZVAL_LONG(pval_arg, (long)var_arg->ulVal);
+                               ZVAL_LONG(pval_arg, (long)V_UI4(var_arg));
                        }
                        break;
 
                case VT_INT:
-                       if(var_arg->vt & VT_BYREF)
+                       if(V_ISBYREF(var_arg))
                        {
-                               ZVAL_LONG(pval_arg, (long)*(var_arg->pintVal));
+                               ZVAL_LONG(pval_arg, (long)*V_INTREF(var_arg));
                        }
                        else
                        {
-                               ZVAL_LONG(pval_arg, (long)var_arg->intVal);
+                               ZVAL_LONG(pval_arg, (long)V_INT(var_arg));
                        }
                        break;
 
                case VT_UINT:
-                       if(var_arg->vt & VT_BYREF)
+                       if(V_ISBYREF(var_arg))
                        {
-                               ZVAL_LONG(pval_arg, (long)*(var_arg->puintVal));
+                               ZVAL_LONG(pval_arg, (long)*V_UINTREF(var_arg));
                        }
                        else
                        {
-                               ZVAL_LONG(pval_arg, (long)var_arg->uintVal);
+                               ZVAL_LONG(pval_arg, (long)V_UINT(var_arg));
                        }
                        break;
 
                default:
-                       php_error(E_WARNING,"Unsupported variant type: %d (0x%X)", var_arg->vt, var_arg->vt);
+                       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;
index 9bd8f0983f67ae6f199fe56f6058d60be1854108..9550113a06aa3b6e5542941a2b06cde5fdbfe97d 100644 (file)
@@ -72,6 +72,7 @@ PHP_FUNCTION(com_release);
 PHP_FUNCTION(com_propget);
 PHP_FUNCTION(com_propput);
 PHP_FUNCTION(com_load_typelib);
+PHP_FUNCTION(com_isenum);
 
 PHPAPI int php_COM_get_le_idispatch();
 static ITypeLib *php_COM_find_typelib(char *search_string, int mode);
@@ -84,16 +85,20 @@ function_entry COM_functions[] = {
        PHP_FE(com_load,                                NULL)
        PHP_FE(com_invoke,                              NULL)
        PHP_FE(com_addref,                              NULL)
-       PHP_FE(com_release,                                     NULL)
+       PHP_FE(com_release,                             NULL)
        PHP_FE(com_propget,                             NULL)
        PHP_FE(com_propput,                             NULL)
        PHP_FE(com_load_typelib,                        NULL)
+       PHP_FE(com_isenum,                              NULL)
 
        PHP_FALIAS(com_get,         com_propget,        NULL)
        PHP_FALIAS(com_propset,     com_propput,        NULL)
        PHP_FALIAS(com_set,         com_propput,        NULL)
 
-       {NULL, NULL, NULL}
+       
+       {
+               NULL, NULL, NULL
+       }
 };
 
 static PHP_MINFO_FUNCTION(COM)
@@ -101,21 +106,19 @@ static PHP_MINFO_FUNCTION(COM)
        DISPLAY_INI_ENTRIES();
 }
 
-PHPAPI HRESULT php_COM_invoke(i_dispatch *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)
 {
        HRESULT hr;
        int failed = FALSE;
 
-       if(obj->referenced)
+       if(C_ISREFD(obj))
        {
-               if(obj->typelib)
+               if(C_HASTLIB(obj))
                {
-                       hr = obj->i.typeinfo->lpVtbl->Invoke(obj->i.typeinfo, obj->i.dispatch, dispIdMember,
-                                                                                                  wFlags, pDispParams, pVarResult, NULL, NULL);
+                       hr = C_TYPEINFO_VT(obj)->Invoke(C_TYPEINFO(obj), C_DISPATCH(obj), dispIdMember, wFlags, pDispParams, pVarResult, NULL, NULL);
                        if(FAILED(hr))
                        {
-                               hr = obj->i.dispatch->lpVtbl->Invoke(obj->i.dispatch, 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, NULL, NULL);
                                if(SUCCEEDED(hr))
                                {
                                        /*
@@ -123,15 +126,14 @@ PHPAPI HRESULT php_COM_invoke(i_dispatch *obj, DISPID dispIdMember, WORD wFlags,
                                         * Release ITypeLib and fall back to IDispatch
                                         */
 
-                                       obj->i.typeinfo->lpVtbl->Release(obj->i.typeinfo);
-                                       obj->typelib = FALSE;
+                                       C_TYPEINFO_VT(obj)->Release(C_TYPEINFO(obj));
+                                       C_HASTLIB(obj) = FALSE;
                                }
                        }
                }
                else
                {
-                       hr = obj->i.dispatch->lpVtbl->Invoke(obj->i.dispatch, 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, NULL, NULL);
                }
 
                return hr;
@@ -142,19 +144,19 @@ PHPAPI HRESULT php_COM_invoke(i_dispatch *obj, DISPID dispIdMember, WORD wFlags,
        }
 }
 
-PHPAPI HRESULT php_COM_get_ids_of_names(i_dispatch *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)
 {
        HRESULT hr;
 
-       if(obj->referenced)
+       if(C_ISREFD(obj))
        {
-               if(obj->typelib)
+               if(C_HASTLIB(obj))
                {
-                       hr = obj->i.typeinfo->lpVtbl->GetIDsOfNames(obj->i.typeinfo, rgszNames, 1, rgDispId);
+                       hr = C_TYPEINFO_VT(obj)->GetIDsOfNames(C_TYPEINFO(obj), rgszNames, 1, rgDispId);
 
                        if(FAILED(hr))
                        {
-                               hr = obj->i.dispatch->lpVtbl->GetIDsOfNames(obj->i.dispatch, &IID_NULL, rgszNames, 1, LOCALE_SYSTEM_DEFAULT, rgDispId);
+                               hr = C_DISPATCH_VT(obj)->GetIDsOfNames(C_DISPATCH(obj), &IID_NULL, rgszNames, 1, LOCALE_SYSTEM_DEFAULT, rgDispId);
 
                                if(SUCCEEDED(hr))
                                {
@@ -163,14 +165,14 @@ PHPAPI HRESULT php_COM_get_ids_of_names(i_dispatch *obj, OLECHAR FAR* FAR* rgszN
                                         * Release ITypeLib and fall back to IDispatch
                                         */
 
-                                       obj->i.typeinfo->lpVtbl->Release(obj->i.typeinfo);
-                                       obj->typelib = FALSE;
+                                       C_TYPEINFO_VT(obj)->Release(C_TYPEINFO(obj));
+                                       C_HASTLIB(obj) = FALSE;
                                }
                        }
                }
                else
                {
-                       hr = obj->i.dispatch->lpVtbl->GetIDsOfNames(obj->i.dispatch, &IID_NULL, rgszNames, 1, LOCALE_SYSTEM_DEFAULT, rgDispId);
+                       hr = C_DISPATCH_VT(obj)->GetIDsOfNames(C_DISPATCH(obj), &IID_NULL, rgszNames, 1, LOCALE_SYSTEM_DEFAULT, rgDispId);
                }
 
                return hr;
@@ -181,72 +183,104 @@ PHPAPI HRESULT php_COM_get_ids_of_names(i_dispatch *obj, OLECHAR FAR* FAR* rgszN
        }
 }
 
-PHPAPI HRESULT php_COM_release(i_dispatch *obj)
+PHPAPI HRESULT php_COM_release(comval *obj)
 {
-       if(obj->referenced > 1)
+       if(obj->refcount > 1)
        {
-               obj->referenced--;
+               C_RELEASE(obj);
        }
-       else if(obj->referenced == 1)
+       else if(obj->refcount == 1)
        {
-               if(obj->typelib)
+               if(C_HASTLIB(obj))
                {
-                       obj->i.typeinfo->lpVtbl->Release(obj->i.typeinfo);
+                       C_TYPEINFO_VT(obj)->Release(C_TYPEINFO(obj));
                }
-               obj->i.dispatch->lpVtbl->Release(obj->i.dispatch);
-               obj->referenced--;
+               if(C_HASENUM(obj))
+               {
+                       C_ENUMVARIANT_VT(obj)->Release(C_ENUMVARIANT(obj));
+               }
+               C_DISPATCH_VT(obj)->Release(C_DISPATCH(obj));
+               C_RELEASE(obj);
        }
 
-       return obj->referenced;
+       return obj->refcount;
 }
 
-PHPAPI HRESULT php_COM_addref(i_dispatch *obj)
+PHPAPI HRESULT php_COM_addref(comval *obj)
 {
-       if(obj->referenced)
+       if(C_ISREFD(obj))
        {
-               obj->referenced++;
+               C_ADDREF(obj);
        }
 
-       return obj->referenced;
+       return obj->refcount;
 }
 
-PHPAPI HRESULT php_COM_set(i_dispatch *obj, IDispatch FAR* pDisp, int cleanup)
+PHPAPI HRESULT php_COM_set(comval *obj, IDispatch FAR* pDisp, int cleanup)
 {
        HRESULT hr = 1;
+       DISPPARAMS dispparams;
+       VARIANT var_result;
+
+       C_DISPATCH(obj) = pDisp;
+       obj->refcount = 1;
+       C_HASTLIB(obj) = SUCCEEDED(C_DISPATCH_VT(obj)->GetTypeInfo(C_DISPATCH(obj), 0, LANG_NEUTRAL, &C_TYPEINFO(obj)));
+
+       dispparams.rgvarg = NULL;
+       dispparams.rgdispidNamedArgs = NULL;
+       dispparams.cArgs = 0;
+       dispparams.cNamedArgs = 0;
 
-       obj->i.dispatch = pDisp;
-       obj->referenced = 1;
-       obj->typelib = SUCCEEDED(obj->i.dispatch->lpVtbl->GetTypeInfo(obj->i.dispatch, 0, LANG_NEUTRAL, &obj->i.typeinfo));
+       if(C_HASENUM(obj) = SUCCEEDED(C_DISPATCH_VT(obj)->Invoke(C_DISPATCH(obj), DISPID_NEWENUM, &IID_NULL, LOCALE_SYSTEM_DEFAULT,
+                                                                       DISPATCH_METHOD|DISPATCH_PROPERTYGET, &dispparams, &var_result, NULL, NULL)))
+       {
+               if (V_VT(&var_result) == VT_UNKNOWN)
+               {
+                   C_HASENUM(obj) = SUCCEEDED(V_UNKNOWN(&var_result)->lpVtbl->QueryInterface(V_UNKNOWN(&var_result), &IID_IEnumVARIANT,
+                                                                       (void**)&C_ENUMVARIANT(obj)));
+               }
+               else if (V_VT(&var_result) == VT_DISPATCH)
+               {
+                   C_HASENUM(obj) = SUCCEEDED(V_DISPATCH(&var_result)->lpVtbl->QueryInterface(V_DISPATCH(&var_result), &IID_IEnumVARIANT,
+                                                                       (void**)&C_ENUMVARIANT(obj)));
+               }
+
+       }
 
        if(!cleanup)
        {
-               hr = obj->i.dispatch->lpVtbl->AddRef(obj->i.dispatch);
+               hr = C_DISPATCH_VT(obj)->AddRef(C_DISPATCH(obj));
        }
 
        return hr;
 }
 
-PHPAPI HRESULT php_COM_clone(i_dispatch *obj, i_dispatch *clone, int cleanup)
+PHPAPI HRESULT php_COM_clone(comval *obj, comval *clone, int cleanup)
 {
        HRESULT hr;
 
-       obj->typelib = clone->typelib;
-       obj->i.dispatch = clone->i.dispatch;
-       obj->i.typeinfo = clone->i.typeinfo;
+       C_HASTLIB(obj) = C_HASTLIB(clone);
+       C_HASENUM(obj) = C_HASENUM(obj);
+       C_DISPATCH(obj) = C_DISPATCH(clone);
+       C_TYPEINFO(obj) = C_TYPEINFO(clone);
 
-       if(cleanup || !obj->referenced)
+       if(cleanup || !C_ISREFD(obj))
        {
-               obj->referenced = clone->referenced;
-               clone->referenced = 0;
+               obj->refcount = clone->refcount;
+               C_ISREFD(clone) = FALSE;
        }
        else
        {
-               if(obj->typelib)
+               if(C_HASTLIB(obj))
+               {
+                       C_TYPEINFO_VT(obj)->AddRef(C_TYPEINFO(obj));
+               }
+               if(C_HASENUM(obj))
                {
-                       obj->i.typeinfo->lpVtbl->AddRef(obj->i.typeinfo);
+                       C_ENUMVARIANT_VT(obj)->AddRef(C_ENUMVARIANT(obj));
                }
-               hr = obj->i.dispatch->lpVtbl->AddRef(obj->i.dispatch);
-               obj->referenced = 1;
+               hr = C_DISPATCH_VT(obj)->AddRef(C_DISPATCH(obj));
+               obj->refcount = 1;
        }
 
        return hr;
@@ -282,8 +316,8 @@ static char *php_string_from_clsid(const CLSID *clsid)
 
 static void php_idispatch_destructor(zend_rsrc_list_entry *rsrc)
 {
-       i_dispatch *obj = (i_dispatch *)rsrc->ptr;
-       while(obj->referenced)
+       comval *obj = (comval *)rsrc->ptr;
+       while(C_ISREFD(obj))
        {
                php_COM_release(obj);
        }
@@ -330,7 +364,7 @@ static PHP_INI_MH(OnTypelibFileChange)
                        continue;
                }
                typelib_name = php_strtok_r(typelib_name_buffer, "\r\n", &strtok_buf); /* get rid of newlines */
-               if (typelib_name == NULL)
+               if(typelib_name == NULL)
                {
                        continue;
                }
@@ -345,12 +379,12 @@ static PHP_INI_MH(OnTypelibFileChange)
                }
 
                /* Remove leading/training white spaces on search_string */
-               while (isspace(*typelib_name)) /* Ends on '\0' in worst case */
+               while(isspace(*typelib_name)) /* Ends on '\0' in worst case */
                {
                        typelib_name ++;
                }
                ptr = typelib_name + strlen(typelib_name) - 1;
-               while ((ptr != typelib_name) && isspace(*ptr))
+               while((ptr != typelib_name) && isspace(*ptr))
                {
                        *ptr = '\0';
                        ptr--;
@@ -400,7 +434,7 @@ PHP_FUNCTION(com_load)
        CLSID clsid;
        HRESULT hr;
        OLECHAR *ProgID;
-       i_dispatch *obj;
+       comval *obj;
        char *error_message;
        char *clsid_str;
        int mode = CONST_PERSISTENT;
@@ -408,7 +442,7 @@ PHP_FUNCTION(com_load)
 
 
        codepage = CP_ACP;
-       
+
        switch(ZEND_NUM_ARGS())
        {
                case 1:
@@ -431,7 +465,7 @@ PHP_FUNCTION(com_load)
 
                        convert_to_string_ex(&typelib);
                        convert_to_long_ex(&code_page);
-                       codepage = code_page->value.lval;
+                       codepage = Z_LVAL_P(code_page);
 
                        break;
 
@@ -441,7 +475,7 @@ PHP_FUNCTION(com_load)
 
        if(server_name != NULL)
        {
-               if(server_name->type == IS_NULL)
+               if(Z_TYPE_P(server_name) == IS_NULL)
                {
                        server_name = NULL;
                }
@@ -460,73 +494,103 @@ PHP_FUNCTION(com_load)
        }
 
        convert_to_string_ex(&module_name);
-       ProgID = php_char_to_OLECHAR(module_name->value.str.val, module_name->value.str.len, codepage);
-       hr=CLSIDFromProgID(ProgID, &clsid);
-       efree(ProgID);
+       ProgID = php_char_to_OLECHAR(Z_STRVAL_P(module_name), Z_STRLEN_P(module_name), codepage);
+       obj = (comval *) emalloc(sizeof(comval));
 
        /* obtain CLSID */
-       if(FAILED(hr))
+       if(FAILED(CLSIDFromProgID(ProgID, &clsid)))
        {
-               error_message = php_COM_error_message(hr);  
-               php_error(E_WARNING,"Invalid ProgID:  %s\n", error_message);
-               LocalFree(error_message);
-               RETURN_FALSE;
-       }
+               /* Perhaps this is a Moniker? */
+               IBindCtx *pBindCtx;
+               IMoniker *pMoniker;
+               ULONG ulEaten;
 
-       obj = (i_dispatch *) emalloc(sizeof(i_dispatch));
+               /* TODO: if(server_name) */
 
-       /* obtain IDispatch */
-       if(!server_name)
-       {
-               hr = CoCreateInstance(&clsid, NULL, CLSCTX_SERVER, &IID_IDispatch, (LPVOID *) &(obj->i.dispatch));
+               if(!server_name)
+               {
+                       if(SUCCEEDED(hr = CreateBindCtx(0, &pBindCtx)))
+                       {
+                               if(SUCCEEDED(hr = MkParseDisplayName(pBindCtx, ProgID, &ulEaten, &pMoniker)))
+                               {
+                                       hr = pMoniker->lpVtbl->BindToObject(pMoniker, pBindCtx, NULL, &IID_IDispatch, (LPVOID *) &C_DISPATCH(obj));
+                                       pMoniker->lpVtbl->Release(pMoniker);
+                               }
+                               pBindCtx->lpVtbl->Release(pBindCtx);
+                       }
+               }
+               else
+               {
+                       hr = MK_E_SYNTAX;
+               }
+               
+               efree(ProgID);
+               
+               if(FAILED(hr))
+               {
+                       efree(obj);
+                       error_message = php_COM_error_message(hr);  
+                       php_error(E_WARNING,"Invalid ProgID or Moniker:  %s\n", error_message);
+                       LocalFree(error_message);
+                       RETURN_FALSE;
+               }
        }
        else
        {
-               COSERVERINFO server_info;
-               MULTI_QI pResults;
-
-               server_info.dwReserved1=0;
-               server_info.dwReserved2=0;
-               server_info.pwszName = php_char_to_OLECHAR(server_name->value.str.val, server_name->value.str.len, codepage);
-               server_info.pAuthInfo=NULL;
+               efree(ProgID);
+               /* obtain IDispatch */
+               if(!server_name)
+               {
+                       hr = CoCreateInstance(&clsid, NULL, CLSCTX_SERVER, &IID_IDispatch, (LPVOID *) &C_DISPATCH(obj));
+               }
+               else
+               {
+                       COSERVERINFO server_info;
+                       MULTI_QI pResults;
+
+                       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.pAuthInfo=NULL;
+
+                       pResults.pIID = &IID_IDispatch;
+                       pResults.pItf = NULL;
+                       pResults.hr = S_OK;
+                       hr=CoCreateInstanceEx(&clsid, NULL, CLSCTX_SERVER, &server_info, 1, &pResults);
+                       if(SUCCEEDED(hr))
+                       {
+                               hr = pResults.hr;
+                               C_DISPATCH(obj) = (IDispatch *) pResults.pItf;
+                       }
+                       efree(server_info.pwszName);
+               }
 
-               pResults.pIID = &IID_IDispatch;
-               pResults.pItf = NULL;
-               pResults.hr = S_OK;
-               hr=CoCreateInstanceEx(&clsid, NULL, CLSCTX_SERVER, &server_info, 1, &pResults);
-               if(SUCCEEDED(hr))
+               if(FAILED(hr))
                {
-                       hr = pResults.hr;
-                       obj->i.dispatch = (IDispatch *) pResults.pItf;
+                       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);
+                       LocalFree(error_message);
+                       efree(clsid_str);
+                       efree(obj);
+                       RETURN_FALSE;
                }
-               efree(server_info.pwszName);
        }
 
-       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);
-               LocalFree(error_message);
-               efree(clsid_str);
-               efree(obj);
-               RETURN_FALSE;
-       }
+       php_COM_set(obj, C_DISPATCH(obj), TRUE);
 
-       php_COM_set(obj, obj->i.dispatch, TRUE);
-       
        if(INI_INT("com.autoregister_casesensitive"))
        {
                mode |= CONST_CS;
        }
 
-       if(obj->typelib)
+       if(C_HASTLIB(obj))
        {
                if(INI_INT("com.autoregister_typelib"))
                {
                        unsigned int idx;
 
-                       if(obj->i.typeinfo->lpVtbl->GetContainingTypeLib(obj->i.typeinfo, &pTL, &idx) == S_OK)
+                       if(C_TYPEINFO_VT(obj)->GetContainingTypeLib(C_TYPEINFO(obj), &pTL, &idx) == S_OK)
                        {
                                php_COM_load_typelib(pTL, mode);
                                pTL->lpVtbl->Release(pTL);
@@ -539,9 +603,9 @@ PHP_FUNCTION(com_load)
                {
                        ITypeLib *pTL;
 
-                       if((pTL = php_COM_find_typelib(typelib->value.str.val, mode)) != NULL)
+                       if((pTL = php_COM_find_typelib(Z_STRVAL_P(typelib), mode)) != NULL)
                        {
-                               obj->typelib = SUCCEEDED(pTL->lpVtbl->GetTypeInfo(pTL, 0, &obj->i.typeinfo));
+                               C_HASTLIB(obj) = SUCCEEDED(pTL->lpVtbl->GetTypeInfo(pTL, 0, &C_TYPEINFO(obj)));
                                /* idx 0 should deliver the ITypeInfo for the IDispatch Interface */
                                if(INI_INT("com.autoregister_typelib"))
                                {
@@ -557,56 +621,166 @@ PHP_FUNCTION(com_load)
 /* }}} */
 
 
-int do_COM_invoke(i_dispatch *obj, pval *function_name, VARIANTARG *var_result, pval **arguments, int arg_count)
+int do_COM_invoke(comval *obj, pval *function_name, VARIANT *var_result, pval **arguments, int arg_count)
 {
        DISPID dispid;
        HRESULT hr;
        OLECHAR *funcname;
        char *error_message;
-       VARIANTARG *variant_args;
+       VARIANT *variant_args;
        int current_arg, current_variant;
        DISPPARAMS dispparams;
+       SAFEARRAY *pSA;
 
-       funcname = php_char_to_OLECHAR(function_name->value.str.val, function_name->value.str.len, codepage);
+       if(C_HASENUM(obj) && strstr(Z_STRVAL_P(function_name), "next"))
+       {
+               // Grab one argument off the stack, allocate enough
+               // VARIANTs
+               // Get the IEnumVariant interface and call ->Next();
+               SAFEARRAYBOUND rgsabound[1];
+               unsigned long count;
 
-       hr = php_COM_get_ids_of_names(obj, &funcname, &dispid);
+               switch(arg_count)
+               {
+                       case 0:
+                               count = 1;
+                               break;
 
-       if(FAILED(hr))
-       {
-               error_message = php_COM_error_message(hr);
-               php_error(E_WARNING,"Unable to lookup %s:  %s\n", function_name->value.str.val, error_message);
-               LocalFree(error_message);
-               efree(funcname);
-               return FAILURE;
-       }
+                       case 1:
+                               convert_to_long_ex(&arguments[0]);
+                               count = Z_LVAL_P(arguments[0]);
+                               break;
 
-       variant_args = (VARIANTARG *) emalloc(sizeof(VARIANTARG)*arg_count);
+                       default:
+                               /* TODO: complain about wrong arg count */
+                               php_error(E_WARNING,"Wrong argument count to IEnumVariant::Next()\n");
+
+                               return FAILURE;
+               }
+
+               rgsabound[0].lLbound = 0;
+               rgsabound[0].cElements = count;
+
+               if((pSA = SafeArrayCreate(VT_VARIANT, 1, rgsabound)) == NULL)
+               {
+                       VariantInit(var_result);
+                       return FAILURE;
+               }
+               else
+               {
+                       V_ARRAY(var_result) = pSA;
+                       V_VT(var_result) = VT_VARIANT|VT_ARRAY;
+               }
+
+               if(FAILED(hr = C_ENUMVARIANT_VT(obj)->Next(C_ENUMVARIANT(obj), count, pSA->pvData, &count)))
+               {
+                       char *error_message = php_COM_error_message(hr);
+                       php_error(E_WARNING,"IEnumVariant::Next() failed:  %s\n", error_message);
+                       efree(error_message);
+                       SafeArrayDestroy(pSA);
+                       VariantInit(var_result);
+                       return FAILURE;
+               }
+
+               if(count != rgsabound[0].cElements)
+               {
+                       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);
+                               efree(error_message);
+                               SafeArrayDestroy(pSA);
+                               VariantInit(var_result);
+                               return FAILURE;
+                       }
+               }
 
-       for(current_arg=0; current_arg<arg_count; current_arg++)
+               return SUCCESS;
+       }
+       else if(C_HASENUM(obj) && strstr(Z_STRVAL_P(function_name), "reset"))
        {
-               current_variant = arg_count - current_arg - 1;
-               php_pval_to_variant(arguments[current_arg], &variant_args[current_variant], codepage);
+               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);
+                       efree(error_message);
+                       return FAILURE;
+               }
+               return SUCCESS;
        }
+       else if(C_HASENUM(obj) && strstr(Z_STRVAL_P(function_name), "skip"))
+       {
+               unsigned long count;
 
-       dispparams.rgvarg = variant_args;
-       dispparams.rgdispidNamedArgs = NULL;
-       dispparams.cArgs = arg_count;
-       dispparams.cNamedArgs = 0;
+               switch(arg_count)
+               {
+                       case 0:
+                               count = 1;
+                               break;
 
-       hr = php_COM_invoke(obj, dispid, DISPATCH_METHOD|DISPATCH_PROPERTYGET, &dispparams, var_result);
+                       case 1:
+                               convert_to_long_ex(&arguments[0]);
+                               count = Z_LVAL_P(arguments[0]);
+                               break;
 
-       if(FAILED(hr))
+                       default:
+                               php_error(E_WARNING,"Wrong argument count to IEnumVariant::Skip()\n");
+                               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);
+                       efree(error_message);
+                       return FAILURE;
+               }
+               return SUCCESS;
+
+       }
+       else
        {
-               error_message = php_COM_error_message(hr);
-               php_error(E_WARNING,"Invoke() failed:  %s\n", error_message);
-               LocalFree(error_message);
-               efree(funcname);
+               funcname = php_char_to_OLECHAR(Z_STRVAL_P(function_name), Z_STRLEN_P(function_name), codepage);
+
+               hr = php_COM_get_ids_of_names(obj, &funcname, &dispid);
+
+               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);
+                       LocalFree(error_message);
+                       efree(funcname);
+                       return FAILURE;
+               }
+
+               variant_args = (VARIANT*) emalloc(sizeof(VARIANT)*arg_count);
+
+               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);
+               }
+
+               dispparams.rgvarg = variant_args;
+               dispparams.rgdispidNamedArgs = NULL;
+               dispparams.cArgs = arg_count;
+               dispparams.cNamedArgs = 0;
+
+               hr = php_COM_invoke(obj, dispid, DISPATCH_METHOD|DISPATCH_PROPERTYGET, &dispparams, var_result);
+
+               if(FAILED(hr))
+               {
+                       error_message = php_COM_error_message(hr);
+                       php_error(E_WARNING,"Invoke() failed:  %s\n", error_message);
+                       LocalFree(error_message);
+                       efree(funcname);
+                       efree(variant_args);
+                       return FAILURE;
+               }
+
                efree(variant_args);
-               return FAILURE;
+               efree(funcname);
        }
-
-       efree(variant_args);
-       efree(funcname);
        return SUCCESS;
 }
 
@@ -617,10 +791,10 @@ PHP_FUNCTION(com_invoke)
 {
        pval **arguments;
        pval *object, *function_name;
-       i_dispatch *obj;
+       comval *obj;
        int type;
        int arg_count = ZEND_NUM_ARGS();
-       VARIANTARG var_result;
+       VARIANT var_result;
 
        if(arg_count<2)
        {
@@ -637,10 +811,10 @@ PHP_FUNCTION(com_invoke)
 
        /* obtain IDispatch interface */
        convert_to_long(object);
-       obj = (i_dispatch *)zend_list_find(object->value.lval, &type);
+       obj = (comval *)zend_list_find(Z_LVAL_P(object), &type);
        if(!obj || (type!=le_idispatch))
        {
-               php_error(E_WARNING,"%d is not a COM object handler", function_name->value.str.val);
+               php_error(E_WARNING,"%d is not a COM object handler", Z_STRVAL_P(function_name));
                RETURN_FALSE;
        }
 
@@ -662,7 +836,7 @@ PHP_FUNCTION(com_invoke)
 PHP_FUNCTION(com_release)
 {
        pval *object;
-       i_dispatch *obj;
+       comval *obj;
        int type;
        int arg_count = ZEND_NUM_ARGS();
 
@@ -670,23 +844,22 @@ PHP_FUNCTION(com_release)
        {
                WRONG_PARAM_COUNT;
        }
-       
+
        if(getParameters(ht, 1, &object)==FAILURE)
        {
                RETURN_FALSE;
        }
 
        /* obtain IDispatch interface */
-       convert_to_long(object);
-       obj = (i_dispatch *)zend_list_find(object->value.lval, &type);
-       if(!obj || (type!=le_idispatch))
+       convert_to_long_ex(&object);
+       obj = (comval *)zend_list_find(Z_LVAL_P(object), &type);
+       if(!obj || (type != le_idispatch))
        {
                php_error(E_WARNING,"%d is not a COM object handler");
                RETURN_FALSE;
        }
 
-       return_value->type = IS_LONG;
-       return_value->value.lval = php_COM_release(obj);
+       RETURN_LONG(php_COM_release(obj))
 }
 /* }}} */
 
@@ -695,7 +868,7 @@ PHP_FUNCTION(com_release)
 PHP_FUNCTION(com_addref)
 {
        pval *object;
-       i_dispatch *obj;
+       comval *obj;
        int type;
        int arg_count = ZEND_NUM_ARGS();
 
@@ -703,34 +876,31 @@ PHP_FUNCTION(com_addref)
        {
                WRONG_PARAM_COUNT;
        }
-       
+
        if(getParameters(ht, 1, &object)==FAILURE)
        {
                RETURN_FALSE;
        }
 
        /* obtain IDispatch interface */
-       convert_to_long(object);
-       obj = (i_dispatch *)zend_list_find(object->value.lval, &type);
-       if(!obj || (type!=le_idispatch))
+       convert_to_long_ex(&object);
+       obj = (comval *)zend_list_find(Z_LVAL_P(object), &type);
+       if(!obj || (type != le_idispatch))
        {
                php_error(E_WARNING,"%d is not a COM object handler");
                RETURN_FALSE;
        }
 
-       return_value->type = IS_LONG;
-       return_value->value.lval = php_COM_addref(obj);
+       RETURN_LONG(php_COM_addref(obj));
 }
 /* }}} */
 
-static int do_COM_offget(VARIANT *result, i_dispatch *array, pval *property, int cleanup)
+static int do_COM_offget(VARIANT *result, comval *array, pval *property, int cleanup)
 {
        pval function_name;
        int retval;
 
-       function_name.value.str.val = "Item";
-       function_name.value.str.len = 4;
-       function_name.type = IS_STRING;
+       ZVAL_STRINGL(&function_name, "Item", 4, 0);
        retval = do_COM_invoke(array, &function_name, result, &property, 1);
        if(cleanup)
        {
@@ -741,7 +911,7 @@ static int do_COM_offget(VARIANT *result, i_dispatch *array, pval *property, int
        return retval;
 }
 
-static int do_COM_propget(VARIANTARG *var_result, i_dispatch *obj, pval *arg_property, int cleanup)
+static int do_COM_propget(VARIANT *var_result, comval *obj, pval *arg_property, int cleanup)
 {
        DISPID dispid;
        HRESULT hr;
@@ -751,14 +921,14 @@ static int do_COM_propget(VARIANTARG *var_result, i_dispatch *obj, pval *arg_pro
 
 
        /* obtain property handler */
-       propname = php_char_to_OLECHAR(arg_property->value.str.val, arg_property->value.str.len, codepage);
+       propname = php_char_to_OLECHAR(Z_STRVAL_P(arg_property), Z_STRLEN_P(arg_property), codepage);
 
        hr = php_COM_get_ids_of_names(obj, &propname, &dispid);
 
        if(FAILED(hr))
        {
                error_message = php_COM_error_message(hr);
-               php_error(E_WARNING,"Unable to lookup %s:  %s\n", arg_property->value.str.val, error_message);
+               php_error(E_WARNING,"Unable to lookup %s:  %s\n", Z_STRVAL_P(arg_property), error_message);
                LocalFree(error_message);
                efree(propname);
                if(cleanup)
@@ -795,7 +965,7 @@ static int do_COM_propget(VARIANTARG *var_result, i_dispatch *obj, pval *arg_pro
 }
 
 
-static void do_COM_propput(pval *return_value, i_dispatch *obj, pval *arg_property, pval *value)
+static void do_COM_propput(pval *return_value, comval *obj, pval *arg_property, pval *value)
 {
        DISPID dispid;
        HRESULT hr;
@@ -803,21 +973,21 @@ static void do_COM_propput(pval *return_value, i_dispatch *obj, pval *arg_proper
        char *error_message;
        VARIANT *var_result;
        DISPPARAMS dispparams;
-       VARIANTARG new_value;
+       VARIANT new_value;
        DISPID mydispid = DISPID_PROPERTYPUT;
 
 
        var_result = emalloc(sizeof(VARIANT));
 
        /* obtain property handler */
-       propname = php_char_to_OLECHAR(arg_property->value.str.val, arg_property->value.str.len, codepage);
+       propname = php_char_to_OLECHAR(Z_STRVAL_P(arg_property), Z_STRLEN_P(arg_property), codepage);
 
        hr = php_COM_get_ids_of_names(obj, &propname, &dispid);
 
        if(FAILED(hr))
        {
                error_message = php_COM_error_message(hr);
-               php_error(E_WARNING,"Unable to lookup %s:  %s\n", arg_property->value.str.val, error_message);
+               php_error(E_WARNING,"Unable to lookup %s:  %s\n", Z_STRVAL_P(arg_property), error_message);
                LocalFree(error_message);
                efree(propname);
                RETURN_FALSE;
@@ -866,8 +1036,8 @@ PHP_FUNCTION(com_propget)
 {
        pval *arg_idispatch, *arg_property;
        int type;
-       i_dispatch *obj;
-       VARIANTARG var_result;
+       comval *obj;
+       VARIANT var_result;
 
        if(ZEND_NUM_ARGS()!=2 || getParameters(ht, 2, &arg_idispatch, &arg_property)==FAILURE)
        {
@@ -876,10 +1046,10 @@ PHP_FUNCTION(com_propget)
 
        /* obtain IDispatch interface */
        convert_to_long(arg_idispatch);
-       obj = (i_dispatch *)zend_list_find(arg_idispatch->value.lval,&type);
-       if(!obj || (type!=le_idispatch))
+       obj = (comval *)zend_list_find(Z_LVAL_P(arg_idispatch), &type);
+       if(!obj || (type != le_idispatch))
        {
-               php_error(E_WARNING,"%d is not a COM object handler", arg_idispatch->value.lval);
+               php_error(E_WARNING,"%d is not a COM object handler", Z_LVAL_P(arg_idispatch));
        }
        convert_to_string_ex(&arg_property);
 
@@ -898,20 +1068,20 @@ PHP_FUNCTION(com_propput)
 {
        pval *arg_idispatch, *arg_property, *arg_value;
        int type;
-       i_dispatch *obj;
+       comval *obj;
 
        if(ZEND_NUM_ARGS()!=3 || getParameters(ht, 3, &arg_idispatch, &arg_property, &arg_value)==FAILURE)
        {
                WRONG_PARAM_COUNT;
        }
 
-       /* obtain i_dispatch interface */
+       /* obtain comval interface */
        convert_to_long(arg_idispatch);
-       /* obtain i_dispatch interface */
-       obj = (i_dispatch *)zend_list_find(arg_idispatch->value.lval,&type);
-       if(!obj || (type!=le_idispatch))
+       /* obtain comval interface */
+       obj = (comval *)zend_list_find(Z_LVAL_P(arg_idispatch), &type);
+       if(!obj || (type != le_idispatch))
        {
-               php_error(E_WARNING,"%d is not a COM object handler", arg_idispatch->value.lval);
+               php_error(E_WARNING,"%d is not a COM object handler", Z_LVAL_P(arg_idispatch));
        }
        convert_to_string_ex(&arg_property);
 
@@ -944,15 +1114,15 @@ PHP_FUNCTION(com_load_typelib)
        }
 
        convert_to_string_ex(&arg_typelib);
-       pTL = php_COM_find_typelib(arg_typelib->value.str.val, mode);
+       pTL = php_COM_find_typelib(Z_STRVAL_P(arg_typelib), mode);
        if(php_COM_load_typelib(pTL, mode) == SUCCESS)
        {
                pTL->lpVtbl->Release(pTL);
-               RETVAL_TRUE;
+               RETURN_TRUE;
        }
        else
        {
-               RETVAL_FALSE;
+               RETURN_FALSE;
        }
 }
 /* }}} */
@@ -965,26 +1135,27 @@ PHPAPI pval php_COM_get_property_handler(zend_property_reference *property_refer
        pval **idispatch_handle;
        pval *object = property_reference->object;
        int type;
-       i_dispatch *obj, *obj_prop;
+       comval *obj, *obj_prop;
        VARIANT *var_result;
 
-       INIT_ZVAL(return_value);        
+       INIT_ZVAL(return_value);    
        ZVAL_NULL(&return_value);
 
        /* fetch the IDispatch interface */
        zend_hash_index_find(object->value.obj.properties, 0, (void **) &idispatch_handle);
-       obj = (i_dispatch *) zend_list_find((*idispatch_handle)->value.lval, &type);
-       if(!obj || (type!=le_idispatch))
+       obj = (comval *) zend_list_find(Z_LVAL_P(*idispatch_handle), &type);
+       if(!obj || (type != le_idispatch))
        {
                return return_value;
        }
 
-       obj_prop = (i_dispatch *) emalloc(sizeof(i_dispatch));
+       obj_prop = (comval *) emalloc(sizeof(comval));
        var_result = (VARIANT *) emalloc(sizeof(VARIANT));
-       
+
        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:
@@ -1030,27 +1201,27 @@ PHPAPI pval php_COM_get_property_handler(zend_property_reference *property_refer
                                                ZVAL_ADDREF(&return_value);
                                        }
 
-                                       efree(var_result);                              
-                               
+                                       efree(var_result);              
+
                                        return return_value;
                                }
                                break;
                }
 
-               if(var_result->vt == VT_DISPATCH)
+               if(V_VT(var_result) == VT_DISPATCH)
                {
                        pval *handle;
 
-                       if(var_result->pdispVal == NULL)
+                       if(V_DISPATCH(var_result) == NULL)
                        {
-                                       efree(var_result);
-                                       efree(obj_prop);
-                                       return return_value;
+                               efree(var_result);
+                               efree(obj_prop);
+                               return return_value;
                        }
 
                        obj = obj_prop;
-                       
-                       php_COM_set(obj_prop, var_result->pdispVal, TRUE);
+
+                       php_COM_set(obj_prop, V_DISPATCH(var_result), TRUE);
 
                        return_value.type = IS_OBJECT;
                        return_value.value.obj.ce = &com_class_entry;
@@ -1073,7 +1244,7 @@ PHPAPI pval php_COM_get_property_handler(zend_property_reference *property_refer
 
                pval_destructor(&overloaded_property->element);
        }
-       efree(var_result);                              
+       efree(var_result);              
 
        return return_value;
 }
@@ -1085,20 +1256,20 @@ PHPAPI int php_COM_set_property_handler(zend_property_reference *property_refere
        zend_llist_element *element;
        pval **idispatch_handle;
        pval *object = property_reference->object;
-       i_dispatch *obj;
+       comval *obj;
        int type;
-       VARIANTARG var_result;
+       VARIANT var_result;
 
 
        /* fetch the IDispatch interface */
        zend_hash_index_find(object->value.obj.properties, 0, (void **) &idispatch_handle);
-       obj = (i_dispatch *)zend_list_find((*idispatch_handle)->value.lval,&type);
-       if(!obj || (type!=le_idispatch))
+       obj = (comval *)zend_list_find(Z_LVAL_P(*idispatch_handle), &type);
+       if(!obj || (type != le_idispatch))
        {
                return FAILURE;
        }
        var_result.vt = VT_DISPATCH;
-       var_result.pdispVal = obj->i.dispatch;
+       var_result.pdispVal = C_DISPATCH(obj);
 
        for(element=property_reference->elements_list->head; element && element!=property_reference->elements_list->tail; element=element->next)
        {
@@ -1108,7 +1279,7 @@ PHPAPI int php_COM_set_property_handler(zend_property_reference *property_refere
                        case OE_IS_ARRAY:
                                break;
                        case OE_IS_OBJECT:
-                               if(var_result.vt != VT_DISPATCH)
+                               if(V_VT(&var_result) != VT_DISPATCH)
                                {
                                        return FAILURE;
                                }
@@ -1125,13 +1296,13 @@ PHPAPI int php_COM_set_property_handler(zend_property_reference *property_refere
                pval_destructor(&overloaded_property->element);
        }
 
-       if(var_result.vt != VT_DISPATCH)
+       if(V_VT(&var_result) != VT_DISPATCH)
        {
                return FAILURE;
        }
-       obj = (i_dispatch *) emalloc(sizeof(i_dispatch));
-       obj->typelib = FALSE;
-       obj->i.dispatch = var_result.pdispVal;
+       obj = (comval *) emalloc(sizeof(comval));
+       C_HASTLIB(obj) = FALSE;
+       C_DISPATCH(obj) = V_DISPATCH(&var_result);
 
        overloaded_property = (zend_overloaded_element *) element->data;
        do_COM_propput(&result, obj, &overloaded_property->element, value);
@@ -1146,7 +1317,7 @@ PHPAPI void php_COM_call_function_handler(INTERNAL_FUNCTION_PARAMETERS, zend_pro
        pval property, **handle;
        pval *object = property_reference->object;
        zend_overloaded_element *function_name = (zend_overloaded_element *) property_reference->elements_list->tail->data;
-       i_dispatch *obj;
+       comval *obj;
        int type;
 
        if(zend_llist_count(property_reference->elements_list)==1
@@ -1181,7 +1352,7 @@ PHPAPI void php_COM_call_function_handler(INTERNAL_FUNCTION_PARAMETERS, zend_pro
                return;
        }
        zend_hash_index_find(property.value.obj.properties, 0, (void **) &handle);
-       obj = (i_dispatch *)zend_list_find((*handle)->value.lval,&type);
+       obj = (comval *)zend_list_find((*handle)->value.lval,&type);
 
        if(!obj || (type!=le_idispatch))
        {
@@ -1191,16 +1362,14 @@ PHPAPI void php_COM_call_function_handler(INTERNAL_FUNCTION_PARAMETERS, zend_pro
        }
 
        if(zend_llist_count(property_reference->elements_list)==1
-          && !strcmp(function_name->element.value.str.val, "release"))
+          && !strcmp(Z_STRVAL_P(&function_name->element), "release"))
        {
-               return_value->type = IS_LONG;
-               return_value->value.lval = php_COM_release(obj);
+               RETVAL_LONG(php_COM_release(obj));
        }
        else if(zend_llist_count(property_reference->elements_list)==1
-          && !strcmp(function_name->element.value.str.val, "addref"))
+                       && !strcmp(Z_STRVAL_P(&function_name->element), "addref"))
        {
-               return_value->type = IS_LONG;
-               return_value->value.lval = php_COM_addref(obj);
+               RETVAL_LONG(php_COM_addref(obj));
        }
        else
        {
@@ -1209,8 +1378,8 @@ PHPAPI void php_COM_call_function_handler(INTERNAL_FUNCTION_PARAMETERS, zend_pro
                int arg_count = ZEND_NUM_ARGS();
 
                var_result = (VARIANT *) emalloc(sizeof(VARIANT));
-               
-               var_result->vt = VT_EMPTY;
+
+               VariantInit(var_result);
 
                arguments = (pval **) emalloc(sizeof(pval *)*arg_count);
                getParametersArray(ht, arg_count, arguments);
@@ -1219,8 +1388,10 @@ PHPAPI void php_COM_call_function_handler(INTERNAL_FUNCTION_PARAMETERS, zend_pro
                {
                        RETVAL_FALSE;
                }
-
-               php_variant_to_pval(var_result, return_value, 0, codepage);
+               else
+               {
+                       php_variant_to_pval(var_result, return_value, 0, codepage);
+               }
 
                efree(arguments);
                efree(var_result);
@@ -1328,12 +1499,12 @@ 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;
                        }
-                       if (ERROR_SUCCESS != RegQueryInfoKey(hkey, NULL, NULL, NULL, &SubKeys, &MaxSubKeyLength, NULL, NULL, NULL, NULL, NULL, NULL))
+                       if(ERROR_SUCCESS != RegQueryInfoKey(hkey, NULL, NULL, NULL, &SubKeys, &MaxSubKeyLength, NULL, NULL, NULL, NULL, NULL, NULL))
                        {
                                RegCloseKey(hkey);
                                return NULL;
@@ -1341,27 +1512,27 @@ static ITypeLib *php_COM_find_typelib(char *search_string, int mode)
                        MaxSubKeyLength++; /* \0 is not counted */
                        keyname = emalloc(MaxSubKeyLength);
                        libname = emalloc(strlen(search_string)+1);
-                       for (ii=0;ii<SubKeys;ii++)
+                       for(ii=0;ii<SubKeys;ii++)
                        {
-                               if (ERROR_SUCCESS != RegEnumKey(hkey, ii, keyname, MaxSubKeyLength))
+                               if(ERROR_SUCCESS != RegEnumKey(hkey, ii, keyname, MaxSubKeyLength))
                                {
                                        /* Failed - who cares */
                                        continue;
                                }
-                               if (ERROR_SUCCESS != RegOpenKey(hkey, keyname, &hsubkey))
+                               if(ERROR_SUCCESS != RegOpenKey(hkey, keyname, &hsubkey))
                                {
                                        /* Failed - who cares */
                                        continue;
                                }
-                               if (ERROR_SUCCESS != RegQueryInfoKey(hsubkey, NULL, NULL, NULL, &VersionCount, NULL, NULL, NULL, NULL, NULL, NULL, NULL))
+                               if(ERROR_SUCCESS != RegQueryInfoKey(hsubkey, NULL, NULL, NULL, &VersionCount, NULL, NULL, NULL, NULL, NULL, NULL, NULL))
                                {
                                        /* Failed - who cares */
                                        RegCloseKey(hsubkey);
                                        continue;
                                }
-                               for (jj=0;jj<VersionCount;jj++)
+                               for(jj=0;jj<VersionCount;jj++)
                                {
-                                       if (ERROR_SUCCESS != RegEnumKey(hsubkey, jj, version, sizeof(version)))
+                                       if(ERROR_SUCCESS != RegEnumKey(hsubkey, jj, version, sizeof(version)))
                                        {
                                                /* Failed - who cares */
                                                continue;
@@ -1369,9 +1540,9 @@ static ITypeLib *php_COM_find_typelib(char *search_string, int mode)
                                        /* OK we just need to retrieve the default */
                                        /* value for this key and see if it matches */
                                        libnamelen = strlen(search_string)+1;
-                                       if (ERROR_SUCCESS == RegQueryValue(hsubkey, version, libname, &libnamelen))
+                                       if(ERROR_SUCCESS == RegQueryValue(hsubkey, version, libname, &libnamelen))
                                        {
-                                               if ((mode & CONST_CS) ? (strcmp(libname, search_string) == 0) : (stricmp(libname, search_string) == 0))
+                                               if((mode & CONST_CS) ? (strcmp(libname, search_string) == 0) : (stricmp(libname, search_string) == 0))
                                                {
                                                        char *str;
                                                        int major, minor;
@@ -1385,7 +1556,7 @@ static ITypeLib *php_COM_find_typelib(char *search_string, int mode)
                                                        /* Or just parse the version string and pass that in */
                                                        /* The version string seems like a more portable solution */
                                                        /* Given that there is a COM on Unix */
-                                                       if (2 != sscanf(version, "%d.%d", &major, &minor))
+                                                       if(2 != sscanf(version, "%d.%d", &major, &minor))
                                                        {
                                                                major = 1;
                                                                minor = 0;
@@ -1425,7 +1596,7 @@ static int php_COM_load_typelib(ITypeLib *TypeLib, int mode)
        int interfaces;
        ELS_FETCH();
 
-       if (NULL == TypeLib)
+       if(NULL == TypeLib)
        {
                return FAILURE;
        }
@@ -1487,6 +1658,35 @@ static int php_COM_load_typelib(ITypeLib *TypeLib, int mode)
        return SUCCESS;
 }
 
+/* {{{ proto bool com_isenum(com_module obj)
+   Grabs an IEnumVariant */
+PHP_FUNCTION(com_isenum)
+{
+       pval *object;
+       pval **idispatch_handle;
+       comval *obj;
+       int type;
+
+       if(ZEND_NUM_ARGS() != 1)
+       {
+               WRONG_PARAM_COUNT;
+       }
+
+       getParameters(ht, 1, &object);
+
+       /* obtain IDispatch interface */
+       zend_hash_index_find(object->value.obj.properties, 0, (void **) &idispatch_handle);
+       obj = (comval *) zend_list_find((*idispatch_handle)->value.lval, &type);
+       if(!obj || (type!=le_idispatch))
+       {
+               php_error(E_WARNING,"%s is not a COM object handler", "");
+               RETURN_FALSE;
+       }
+
+       RETURN_BOOL(C_HASENUM(obj));
+}
+/* }}} */
+
 void php_register_COM_class()
 {
        INIT_OVERLOADED_CLASS_ENTRY(com_class_entry, "COM", NULL,
index 6c08f26e64ac7531cd7ee699650703f540e71042..0679cd162b7b4d03070d05e4e09d098278b49c1d 100644 (file)
@@ -5,21 +5,38 @@
 
 #include "oleauto.h"
 
-typedef struct i_dispatch_ {
-       int typelib;
-       int referenced;
+typedef struct comval_ {
+       BOOL typelib;
+       BOOL enumeration;
+       int refcount;
        struct {
                IDispatch *dispatch;
                ITypeInfo *typeinfo;
+               IEnumVARIANT *enumvariant;
        } i;
-} i_dispatch;
-
-PHPAPI HRESULT php_COM_invoke(i_dispatch *obj, DISPID dispIdMember, WORD wFlags, DISPPARAMS FAR*  pDispParams, VARIANT FAR* pVarResult);
-PHPAPI HRESULT php_COM_get_ids_of_names(i_dispatch *obj, OLECHAR FAR* FAR* rgszNames, DISPID FAR* rgDispId);
-PHPAPI HRESULT php_COM_release(i_dispatch *obj);
-PHPAPI HRESULT php_COM_addref(i_dispatch *obj);
-PHPAPI HRESULT php_COM_set(i_dispatch *obj, IDispatch FAR* pDisp, int cleanup);
-PHPAPI HRESULT php_COM_clone(i_dispatch *obj, i_dispatch *clone, int cleanup);
+} comval;
+
+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);
+
+#define C_HASTLIB(x)   ((x)->typelib)
+#define C_HASENUM(x)   ((x)->enumeration)
+#define C_ISREFD(x)    ((x)->refcount)
+
+#define C_DISPATCH(x)  ((x)->i.dispatch)
+#define C_TYPEINFO(x)  ((x)->i.typeinfo)
+#define C_ENUMVARIANT(x)       ((x)->i.enumvariant)
+
+#define C_DISPATCH_VT(x)       (C_DISPATCH(x)->lpVtbl)
+#define C_TYPEINFO_VT(x)       (C_TYPEINFO(x)->lpVtbl)
+#define C_ENUMVARIANT_VT(x)    (C_ENUMVARIANT(x)->lpVtbl)
+
+#define C_ADDREF(x)    (++((x)->refcount))
+#define C_RELEASE(x)   (--((x)->refcount))
 
 #endif  /* PHP_WIN32 */
 
index a105fb2e1b6cca08ebc4379c39d62964cac6b679..d892fa71b56426e0471da1112725dc4a82f8b764 100644 (file)
@@ -40,15 +40,17 @@ PHPAPI void php_pval_to_variant(pval *pval_arg, VARIANT *var_arg, int codepage)
 {
        OLECHAR *unicode_str;
 
-       switch(pval_arg->type)
+       VariantInit(var_arg);
+       
+       switch(Z_TYPE_P(pval_arg))
        {
                case IS_NULL:
-                       var_arg->vt = VT_NULL;
+                       V_VT(var_arg) = VT_NULL;
                        break;
 
                case IS_BOOL:
-                       var_arg->vt = VT_BOOL;
-                       var_arg->boolVal = (short)pval_arg->value.lval;
+                       V_VT(var_arg) = VT_BOOL;
+                       V_BOOL(var_arg) = (short) Z_LVAL_P(pval_arg);
                        break;
 
                case IS_OBJECT:
@@ -59,30 +61,33 @@ PHPAPI void php_pval_to_variant(pval *pval_arg, VARIANT *var_arg, int codepage)
 
                                /* fetch the VARIANT structure */
                                zend_hash_index_find(pval_arg->value.obj.properties, 0, (void **) &var_handle);
-                               var_arg->pvarVal = (VARIANT FAR*) zend_list_find((*var_handle)->value.lval, &type);
-                               var_arg->vt = VT_VARIANT|VT_BYREF;
+
+                               V_VT(var_arg) = VT_VARIANT|VT_BYREF;
+                               V_VARIANTREF(var_arg) = (VARIANT FAR*) zend_list_find(Z_LVAL_P(*var_handle), &type);
                        }
                        else if(!strcmp(pval_arg->value.obj.ce->name, "COM"))
                        {
                                pval **idispatch_handle;
-                               i_dispatch *obj;
+                               comval *obj;
                                int type;
 
                                /* fetch the IDispatch interface */
                                zend_hash_index_find(pval_arg->value.obj.properties, 0, (void **) &idispatch_handle);
-                               obj = (i_dispatch *)zend_list_find((*idispatch_handle)->value.lval, &type);
-                               if(!obj || (type != php_COM_get_le_idispatch()) || !obj->referenced)
+                               obj = (comval *)zend_list_find(Z_LVAL_P(*idispatch_handle), &type);
+                               if(!obj || (type != php_COM_get_le_idispatch()) || !C_ISREFD(obj))
                                {
                                        VariantInit(var_arg);
                                }
                                else
                                {
-                                       var_arg->vt = VT_DISPATCH;
-                                       var_arg->pdispVal = obj->i.dispatch;
+                                       V_VT(var_arg) = VT_DISPATCH;
+                                       V_DISPATCH(var_arg) = C_DISPATCH(obj);
                                }
                        }
                        else
+                       {
                                VariantInit(var_arg);
+                       }
                        break;
 
                case IS_ARRAY:
@@ -99,19 +104,19 @@ PHPAPI void php_pval_to_variant(pval *pval_arg, VARIANT *var_arg, int codepage)
                        break;
 
                case IS_LONG:
-                       var_arg->vt = VT_I4;   /* assuming 32-bit platform */
-                       var_arg->lVal = pval_arg->value.lval;
+                       V_VT(var_arg) = VT_I4;   /* assuming 32-bit platform */
+                       V_I4(var_arg) = Z_LVAL_P(pval_arg);
                        break;
 
                case IS_DOUBLE:
-                       var_arg->vt = VT_R8;   /* assuming 64-bit double precision */
-                       var_arg->dblVal = pval_arg->value.dval;
+                       V_VT(var_arg) = VT_R8;   /* assuming 64-bit double precision */
+                       V_R8(var_arg) = Z_DVAL_P(pval_arg);
                        break;
 
                case IS_STRING:
-                       var_arg->vt = VT_BSTR;
-                       unicode_str = php_char_to_OLECHAR(pval_arg->value.str.val, pval_arg->value.str.len, codepage);
-                       var_arg->bstrVal = SysAllocString(unicode_str);
+                       V_VT(var_arg) = VT_BSTR;
+                       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);
        }
 }
@@ -120,48 +125,48 @@ PHPAPI void php_pval_to_variant_ex(pval *pval_arg, VARIANT *var_arg, pval *pval_
 {
        OLECHAR *unicode_str;
 
-       var_arg->vt = (short) pval_type->value.lval;
+       V_VT(var_arg) = (short)Z_LVAL_P(pval_type);
 
-       switch(var_arg->vt)
+       switch(V_VT(var_arg))
        {
                case VT_UI1:
                        convert_to_long_ex(&pval_arg);
-                       var_arg->bVal = (unsigned char)pval_arg->value.lval;
+                       V_UI1(var_arg) = (unsigned char)Z_LVAL_P(pval_arg);
                        break;
 
                case VT_I2:
                        convert_to_long_ex(&pval_arg);
-                       var_arg->iVal = (short)pval_arg->value.lval;
+                       V_I2(var_arg) = (short)Z_LVAL_P(pval_arg);
                        break;
 
                case VT_I4:
                        convert_to_long_ex(&pval_arg);
-                       var_arg->lVal = pval_arg->value.lval;
+                       V_I4(var_arg) = Z_LVAL_P(pval_arg);
                        break;
 
                case VT_R4:
                        convert_to_double_ex(&pval_arg);
-                       var_arg->fltVal = (float)pval_arg->value.dval;
+                       V_R4(var_arg) = (float)Z_DVAL_P(pval_arg);
                        break;
 
                case VT_R8:
                        convert_to_double_ex(&pval_arg);
-                       var_arg->dblVal = pval_arg->value.dval;
+                       V_R8(var_arg) = Z_DVAL_P(pval_arg);
                        break;
 
                case VT_BOOL:
                        convert_to_boolean_ex(&pval_arg);
-                       var_arg->boolVal = (short)pval_arg->value.lval;
+                       V_BOOL(var_arg) = (short)Z_LVAL_P(pval_arg);
                        break;
 
                case VT_ERROR:
                        convert_to_long_ex(&pval_arg);
-                       var_arg->scode = pval_arg->value.lval;
+                       V_ERROR(var_arg) = Z_LVAL_P(pval_arg);
                        break;
 
                case VT_CY:
                        convert_to_double_ex(&pval_arg);
-                       VarCyFromR8(pval_arg->value.dval, &(var_arg->cyVal));
+                       VarCyFromR8(Z_DVAL_P(pval_arg), &V_CY(var_arg));
                        break;
 
                case VT_DATE:
@@ -178,55 +183,44 @@ PHPAPI void php_pval_to_variant_ex(pval *pval_arg, VARIANT *var_arg, pval *pval_
                                wintime.wMinute = phptime->tm_min;
                                wintime.wSecond = phptime->tm_sec;
 
-                               SystemTimeToVariantTime(&wintime, &(var_arg->date));
+                               SystemTimeToVariantTime(&wintime, &V_DATE(var_arg));
                        }
 
                case VT_BSTR:
                        convert_to_string_ex(&pval_arg);
-                       unicode_str = php_char_to_OLECHAR(pval_arg->value.str.val, pval_arg->value.str.len, codepage);
-                       var_arg->bstrVal = SysAllocString(unicode_str);
+                       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(pval_arg->value.str.val, pval_arg->value.str.len, codepage);
-                       VarDecFromStr(unicode_str, LOCALE_SYSTEM_DEFAULT, 0, &(var_arg->decVal));
+                       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(pval_arg->value.str.val, pval_arg->value.str.len, codepage);
-                       VarDecFromStr(unicode_str, LOCALE_SYSTEM_DEFAULT, 0, var_arg->pdecVal);
+                       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:
                        php_pval_to_variant(pval_arg, var_arg, codepage);
-                       if(var_arg->vt != VT_DISPATCH)
+                       if(V_VT(var_arg) != VT_DISPATCH)
                        {
                                VariantInit(var_arg);
                        }
                        else
                        {
-                               HRESULT hr;
-
-                               hr = var_arg->pdispVal->lpVtbl->QueryInterface(var_arg->pdispVal, &IID_IUnknown, &(var_arg->punkVal));
-
-                               if(FAILED(hr))
-                               {
-                                       php_error(E_WARNING,"can't query IUnknown");
-                                       VariantInit(var_arg);
-                               }
-                               else
-                               {
-                                       var_arg->vt     = VT_UNKNOWN;
-                               }
+                               V_VT(var_arg) = VT_UNKNOWN;
+                               V_UNKNOWN(var_arg) = (IUnknown *) V_DISPATCH(var_arg);
                        }
                        break;
 
                case VT_DISPATCH:
                        php_pval_to_variant(pval_arg, var_arg, codepage);
-                       if(var_arg->vt != VT_DISPATCH)
+                       if(V_VT(var_arg) != VT_DISPATCH)
                        {
                                VariantInit(var_arg);
                        }
@@ -234,37 +228,37 @@ PHPAPI void php_pval_to_variant_ex(pval *pval_arg, VARIANT *var_arg, pval *pval_
 
                case VT_UI1|VT_BYREF:
                        convert_to_long(pval_arg);
-                       var_arg->pbVal = (unsigned char FAR*) &(pval_arg->value.lval);
+                       V_UI1REF(var_arg) = (unsigned char FAR*) &Z_LVAL_P(pval_arg);
                        break;
 
                case VT_I2|VT_BYREF:
                        convert_to_long(pval_arg);
-                       var_arg->piVal = (short FAR*) &(pval_arg->value.lval);
+                       V_I2REF(var_arg) = (short FAR*) &Z_LVAL_P(pval_arg);
                        break;
 
                case VT_I4|VT_BYREF:
                        convert_to_long(pval_arg);
-                       var_arg->plVal = (long FAR*) &(pval_arg->value.lval);
+                       V_I4REF(var_arg) = (long FAR*) &Z_LVAL_P(pval_arg);
                        break;
 
                case VT_R4|VT_BYREF:
                        convert_to_double(pval_arg);
-                       var_arg->pfltVal = (float FAR*) &(pval_arg->value.lval);
+                       V_R4REF(var_arg) = (float FAR*) &Z_LVAL_P(pval_arg);
                        break;
 
                case VT_R8|VT_BYREF:
                        convert_to_double(pval_arg);
-                       var_arg->pdblVal = (double FAR*) &(pval_arg->value.lval);
+                       V_R8REF(var_arg) = (double FAR*) &Z_LVAL_P(pval_arg);
                        break;
 
                case VT_BOOL|VT_BYREF:
                        convert_to_boolean(pval_arg);
-                       var_arg->pboolVal = (short FAR*) &(pval_arg->value.lval);
+                       V_BOOLREF(var_arg) = (short FAR*) &Z_LVAL_P(pval_arg);
                        break;
 
                case VT_ERROR|VT_BYREF:
                        convert_to_long(pval_arg);
-                       var_arg->pscode = (long FAR*) &(pval_arg->value.lval);
+                       V_ERRORREF(var_arg) = (long FAR*) &Z_LVAL_P(pval_arg);
                        break;
 
                case VT_CY|VT_BYREF:
@@ -291,51 +285,40 @@ PHPAPI void php_pval_to_variant_ex(pval *pval_arg, VARIANT *var_arg, pval *pval_
 
                case VT_BSTR|VT_BYREF:
                        convert_to_string(pval_arg);
-                       var_arg->pbstrVal = (BSTR FAR*) emalloc(sizeof(BSTR FAR*));
-                       unicode_str = php_char_to_OLECHAR(pval_arg->value.str.val, pval_arg->value.str.len, codepage);
-                       *(var_arg->pbstrVal) = SysAllocString(unicode_str);
+                       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:
                        php_pval_to_variant(pval_arg, var_arg, codepage);
-                       if(var_arg->vt != VT_DISPATCH)
+                       if(V_VT(var_arg) != VT_DISPATCH)
                        {
                                VariantInit(var_arg);
                        }
                        else
                        {
-                               HRESULT hr;
-
-                               hr = var_arg->pdispVal->lpVtbl->QueryInterface(var_arg->pdispVal, &IID_IUnknown, &(var_arg->punkVal));
-
-                               if(FAILED(hr))
-                               {
-                                       php_error(E_WARNING,"can't query IUnknown");
-                                       VariantInit(var_arg);
-                               }
-                               else
-                               {
-                                       var_arg->vt     = VT_UNKNOWN|VT_BYREF;
-                               }
+                               V_VT(var_arg) = VT_UNKNOWN|VT_BYREF;
+                               *V_UNKNOWNREF(var_arg) = (IUnknown *) *V_DISPATCHREF(var_arg);
                        }
                        break;
 
                case VT_DISPATCH|VT_BYREF:
                        php_pval_to_variant(pval_arg, var_arg, codepage);
-                       if(var_arg->vt != VT_DISPATCH)
+                       if(V_VT(var_arg) != VT_DISPATCH)
                        {
                                VariantInit(var_arg);
                        }
                        else
                        {
-                               var_arg->vt     |= VT_BYREF;
+                               V_VT(var_arg) |= VT_BYREF;
                        }
                        break;
 
                case VT_VARIANT|VT_BYREF:
                        php_pval_to_variant(pval_arg, var_arg, codepage);
-                       if(var_arg->vt != (VT_VARIANT | VT_BYREF))
+                       if(V_VT(var_arg) != (VT_VARIANT|VT_BYREF)) /* TODO: i don't believe that this works */
                        {
                                VariantInit(var_arg);
                        }
@@ -343,52 +326,52 @@ PHPAPI void php_pval_to_variant_ex(pval *pval_arg, VARIANT *var_arg, pval *pval_
 
                case VT_I1:
                        convert_to_long_ex(&pval_arg);
-                       var_arg->cVal = (char)pval_arg->value.lval;
+                       V_I1(var_arg) = (char)Z_LVAL_P(pval_arg);
                        break;
 
                case VT_UI2:
                        convert_to_long_ex(&pval_arg);
-                       var_arg->uiVal = (unsigned short)pval_arg->value.lval;
+                       V_UI2(var_arg) = (unsigned short)Z_LVAL_P(pval_arg);
                        break;
 
                case VT_UI4:
                        convert_to_long_ex(&pval_arg);
-                       var_arg->ulVal = (unsigned long)pval_arg->value.lval;
+                       V_UI4(var_arg) = (unsigned long)Z_LVAL_P(pval_arg);
                        break;
 
                case VT_INT:
                        convert_to_long_ex(&pval_arg);
-                       var_arg->intVal = (int)pval_arg->value.lval;
+                       V_INT(var_arg) = (int)Z_LVAL_P(pval_arg);
                        break;
 
                case VT_UINT:
                        convert_to_long_ex(&pval_arg);
-                       var_arg->uintVal = (unsigned int)pval_arg->value.lval;
+                       V_UINT(var_arg) = (unsigned int)Z_LVAL_P(pval_arg);
                        break;
 
                case VT_I1|VT_BYREF:
                        convert_to_long(pval_arg);
-                       var_arg->pcVal = (char FAR*) &pval_arg->value.lval;
+                       V_I1REF(var_arg) = (char FAR*) &Z_LVAL_P(pval_arg);
                        break;
 
                case VT_UI2|VT_BYREF:
                        convert_to_long(pval_arg);
-                       var_arg->puiVal = (unsigned short FAR*) &pval_arg->value.lval;
+                       V_UI2REF(var_arg) = (unsigned short FAR*) &Z_LVAL_P(pval_arg);
                        break;
 
                case VT_UI4|VT_BYREF:
                        convert_to_long(pval_arg);
-                       var_arg->pulVal = (unsigned long FAR*) &pval_arg->value.lval;
+                       V_UI4REF(var_arg) = (unsigned long FAR*) &Z_LVAL_P(pval_arg);
                        break;
 
                case VT_INT|VT_BYREF:
                        convert_to_long(pval_arg);
-                       var_arg->pintVal = (int FAR*) &pval_arg->value.lval;
+                       V_INTREF(var_arg) = (int FAR*) &Z_LVAL_P(pval_arg);
                        break;
 
                case VT_UINT|VT_BYREF:
                        convert_to_long(pval_arg);
-                       var_arg->puintVal = (unsigned int FAR*) &pval_arg->value.lval;
+                       V_UINTREF(var_arg) = (unsigned int FAR*) &Z_LVAL_P(pval_arg);
                        break;
 
                default:
@@ -406,7 +389,7 @@ PHPAPI int php_variant_to_pval(VARIANT *var_arg, pval *pval_arg, int persistent,
        INIT_PZVAL(pval_arg);
 
        /* Add SafeArray support */
-       if (var_arg->vt & VT_ARRAY)
+       if (V_ISARRAY(var_arg))
        {
                SAFEARRAY *array = V_ARRAY(var_arg);
                LONG indices[1];
@@ -416,6 +399,7 @@ PHPAPI int php_variant_to_pval(VARIANT *var_arg, pval *pval_arg, int persistent,
                UINT Dims;
                VARIANT vv;
                pval *element;
+               HRESULT hr;
 
                /* TODO: Add support for multi-dimensional SafeArrays */
                /* For now just validate that the SafeArray has one dimension */
@@ -434,7 +418,7 @@ PHPAPI int php_variant_to_pval(VARIANT *var_arg, pval *pval_arg, int persistent,
                        /* Mask off the array bit and assume */
                        /* what is left is the type of the array */
                        /* elements */
-                       vartype = var_arg->vt & ~VT_ARRAY;
+                       vartype = V_VT(var_arg) & ~VT_ARRAY;
                }
                SafeArrayGetUBound(array, 1, &ubound);
                SafeArrayGetLBound(array, 1, &lbound);
@@ -451,8 +435,16 @@ PHPAPI int php_variant_to_pval(VARIANT *var_arg, pval *pval_arg, int persistent,
                        /* Set up a variant to pass to a recursive call */
                        /* So that we do not need to have two copies */
                        /* of the code */
-                       vv.vt = vartype;
-                       if (S_OK != SafeArrayGetElement(array, indices, (VOID *) &(vv.lVal)))
+                       if (VT_VARIANT == vartype)
+                       {
+                               hr = SafeArrayGetElement(array, indices, (VOID *) &(vv));
+                       }
+                       else
+                       {
+                               V_VT(&vv) = vartype;
+                               hr = SafeArrayGetElement(array, indices, (VOID *) &(vv.lVal));
+                       }
+                       if (S_OK != hr)
             {
                                /* Failure to retieve an element probably means the array is sparse */
                                /* So leave the php array sparse too */
@@ -496,57 +488,57 @@ PHPAPI int php_variant_to_pval(VARIANT *var_arg, pval *pval_arg, int persistent,
                        break;
 
                case VT_UI1:
-                       if(var_arg->vt & VT_BYREF)
+                       if(V_ISBYREF(var_arg))
                        {
-                               ZVAL_LONG(pval_arg, (long)*(var_arg->pbVal));
+                               ZVAL_LONG(pval_arg, (long)*V_UI4REF(var_arg));
                        }
                        else
                        {
-                               ZVAL_LONG(pval_arg, (long)var_arg->pbVal);
+                               ZVAL_LONG(pval_arg, (long)V_UI4(var_arg));
                        }
                        break;
 
                case VT_I2:
-                       if(var_arg->vt & VT_BYREF)
+                       if(V_ISBYREF(var_arg))
                        {
-                               ZVAL_LONG(pval_arg, (long )*(var_arg->piVal));
+                               ZVAL_LONG(pval_arg, (long )*V_I2REF(var_arg));
                        }
                        else
                        {
-                               ZVAL_LONG(pval_arg, (long)var_arg->iVal);
+                               ZVAL_LONG(pval_arg, (long)V_I2(var_arg));
                        }
                        break;
 
                case VT_I4:
-                       if(var_arg->vt & VT_BYREF)
+                       if(V_ISBYREF(var_arg))
                        {
-                               ZVAL_LONG(pval_arg, *(var_arg->plVal));
+                               ZVAL_LONG(pval_arg, *V_I4REF(var_arg));
                        }
                        else
                        {
-                               ZVAL_LONG(pval_arg, var_arg->lVal);
+                               ZVAL_LONG(pval_arg, V_I4(var_arg));
                        }
                        break;
 
                case VT_R4:
-                       if(var_arg->vt & VT_BYREF)
+                       if(V_ISBYREF(var_arg))
                        {
-                               ZVAL_DOUBLE(pval_arg, (double)*(var_arg->pfltVal));
+                               ZVAL_DOUBLE(pval_arg, (double)*V_R4REF(var_arg));
                        }
                        else
                        {
-                               ZVAL_DOUBLE(pval_arg, (double)var_arg->fltVal);
+                               ZVAL_DOUBLE(pval_arg, (double)V_R4(var_arg));
                        }
                        break;
 
                case VT_R8:
-                       if(var_arg->vt & VT_BYREF)
+                       if(V_ISBYREF(var_arg))
                        {
-                               ZVAL_DOUBLE(pval_arg, *(var_arg->pdblVal));
+                               ZVAL_DOUBLE(pval_arg, *V_R8REF(var_arg));
                        }
                        else
                        {
-                               ZVAL_DOUBLE(pval_arg, var_arg->dblVal);
+                               ZVAL_DOUBLE(pval_arg, V_R8(var_arg));
                        }
                        break;
 
@@ -554,12 +546,11 @@ PHPAPI int php_variant_to_pval(VARIANT *var_arg, pval *pval_arg, int persistent,
                case VT_DECIMAL:
                        {
                                OLECHAR *unicode_str;
-                               switch(VarBstrFromDec(&var_arg->decVal, LOCALE_SYSTEM_DEFAULT, 0, &unicode_str))
+                               switch(VarBstrFromDec(&V_DECIMAL(var_arg), LOCALE_SYSTEM_DEFAULT, 0, &unicode_str))
                                {
                                        case S_OK:
-                                               
-                                               pval_arg->value.str.val = php_OLECHAR_to_char(unicode_str, &pval_arg->value.str.len, persistent, codepage);
-                                               pval_arg->type = IS_STRING;
+                                               Z_STRVAL_P(pval_arg) = php_OLECHAR_to_char(unicode_str, &Z_STRLEN_P(pval_arg), persistent, codepage);
+                                               Z_TYPE_P(pval_arg) = IS_STRING;
                                                break;
 
                                        default:
@@ -573,25 +564,25 @@ PHPAPI int php_variant_to_pval(VARIANT *var_arg, pval *pval_arg, int persistent,
 
                /* Currency */
                case VT_CY:
-                       if(var_arg->vt & VT_BYREF)
+                       if(V_ISBYREF(var_arg))
                        {
-                               VarR8FromCy(var_arg->cyVal, &(pval_arg->value.dval));
+                               VarR8FromCy(*V_CYREF(var_arg), &Z_DVAL_P(pval_arg));
                        }
                        else
                        {
-                               VarR8FromCy(*(var_arg->pcyVal), &(pval_arg->value.dval));
+                               VarR8FromCy(V_CY(var_arg), &Z_DVAL_P(pval_arg));
                        }
-                       pval_arg->type = IS_DOUBLE;
+                       Z_TYPE_P(pval_arg) = IS_DOUBLE;
                        break;
 
                case VT_BOOL:
-                       if(var_arg->vt & VT_BYREF)
+                       if(V_ISBYREF(var_arg))
                        {
-                               ZVAL_BOOL(pval_arg, *(var_arg->pboolVal));
+                               ZVAL_BOOL(pval_arg, *V_BOOLREF(var_arg));
                        }
                        else
                        {
-                               ZVAL_BOOL(pval_arg, var_arg->boolVal);
+                               ZVAL_BOOL(pval_arg, V_BOOL(var_arg));
                        }
                        break;
 
@@ -601,36 +592,37 @@ PHPAPI int php_variant_to_pval(VARIANT *var_arg, pval *pval_arg, int persistent,
                        break;
 
                case VT_VARIANT:
-                       php_variant_to_pval(var_arg->pvarVal, pval_arg, persistent, codepage);
+                       php_variant_to_pval(V_VARIANTREF(var_arg), pval_arg, persistent, codepage);
                        break;
 
                case VT_BSTR:
-                       if(pval_arg->is_ref == 0  || (var_arg->vt & VT_BYREF) != VT_BYREF)
+                       if(V_ISBYREF(var_arg))
                        {
-                               pval_arg->value.str.val = php_OLECHAR_to_char(var_arg->bstrVal, &pval_arg->value.str.len, persistent, codepage);
-                               SysFreeString(var_arg->bstrVal);
+                               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));
+                               efree(V_BSTRREF(var_arg));
                        }
                        else
                        {
-                               pval_arg->value.str.val = php_OLECHAR_to_char(*(var_arg->pbstrVal), &pval_arg->value.str.len, persistent, codepage);
-                               SysFreeString(*(var_arg->pbstrVal));
-                               efree(var_arg->pbstrVal);
+                               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));
                        }
 
-                       pval_arg->type = IS_STRING;
+                       Z_TYPE_P(pval_arg) = IS_STRING;
                        break;
 
-               case VT_DATE: {
+               case VT_DATE:
+                       {
                                SYSTEMTIME wintime;
                                struct tm phptime;
 
-                               if((var_arg->vt & VT_BYREF) != VT_BYREF)
+                               if(V_ISBYREF(var_arg))
                                {
-                                       VariantTimeToSystemTime(var_arg->date, &wintime);
+                                       VariantTimeToSystemTime(*V_DATEREF(var_arg), &wintime);
                                }
                                else
                                {
-                                       VariantTimeToSystemTime(*(var_arg->pdate), &wintime);
+                                       VariantTimeToSystemTime(V_DATE(var_arg), &wintime);
                                }
 
                                phptime.tm_year  = wintime.wYear - 1900;
@@ -647,15 +639,15 @@ PHPAPI int php_variant_to_pval(VARIANT *var_arg, pval *pval_arg, int persistent,
                        break;
 
                case VT_UNKNOWN:
-                       if(var_arg->punkVal == NULL)
+                       if(V_UNKNOWN(var_arg) == NULL)
                        {
-                               var_arg->pdispVal = NULL;
+                               V_DISPATCH(var_arg) = NULL;
                        }
                        else
                        {
                                HRESULT hr;
 
-                               hr = var_arg->punkVal->lpVtbl->QueryInterface(var_arg->punkVal, &IID_IDispatch, &(var_arg->pdispVal));
+                               hr = V_UNKNOWN(var_arg)->lpVtbl->QueryInterface(var_arg->punkVal, &IID_IDispatch, &V_DISPATCH(var_arg));
 
                                if(FAILED(hr))
                                {
@@ -665,26 +657,26 @@ PHPAPI int php_variant_to_pval(VARIANT *var_arg, pval *pval_arg, int persistent,
                                        php_error(E_WARNING,"Unable to obtain IDispatch interface:  %s", error_message);
                                        LocalFree(error_message);
 
-                                       var_arg->pdispVal = NULL;
+                                       V_DISPATCH(var_arg) = NULL;
                                }
                        }
                        /* break missing intentionaly */
                case VT_DISPATCH:
                        {
                                pval *handle;
-                               i_dispatch *obj;
+                               comval *obj;
 
-                               if(var_arg->pdispVal == NULL)
+                               if(V_DISPATCH(var_arg) == NULL)
                                {
                                        ret = FAILURE;
                                        ZVAL_NULL(pval_arg);
                                }
                                else
                                {
-                                       obj = emalloc(sizeof(i_dispatch));
-                                       php_COM_set(obj, var_arg->pdispVal, TRUE);
+                                       obj = emalloc(sizeof(comval));
+                                       php_COM_set(obj, V_DISPATCH(var_arg), TRUE);
 
-                                       pval_arg->type = IS_OBJECT;
+                                       Z_TYPE_P(pval_arg) = IS_OBJECT;
                                        pval_arg->value.obj.ce = &com_class_entry;
                                        pval_arg->value.obj.properties = (HashTable *) emalloc(sizeof(HashTable));
                                        zend_hash_init(pval_arg->value.obj.properties, 0, NULL, ZVAL_PTR_DTOR, 0);
@@ -700,62 +692,62 @@ PHPAPI int php_variant_to_pval(VARIANT *var_arg, pval *pval_arg, int persistent,
                        break;
 
                case VT_I1:
-                       if(var_arg->vt & VT_BYREF)
+                       if(V_ISBYREF(var_arg))
                        {
-                               ZVAL_LONG(pval_arg, (long)*(var_arg->pcVal));
+                               ZVAL_LONG(pval_arg, (long)*V_I1REF(var_arg));
                        }
                        else
                        {
-                               ZVAL_LONG(pval_arg, (long)var_arg->cVal);
+                               ZVAL_LONG(pval_arg, (long)V_I1(var_arg));
                        }
                        break;
 
                case VT_UI2:
-                       if(var_arg->vt & VT_BYREF)
+                       if(V_ISBYREF(var_arg))
                        {
-                               ZVAL_LONG(pval_arg, (long)*(var_arg->puiVal));
+                               ZVAL_LONG(pval_arg, (long)*V_UI2REF(var_arg));
                        }
                        else
                        {
-                               ZVAL_LONG(pval_arg, (long)var_arg->uiVal);
+                               ZVAL_LONG(pval_arg, (long)V_UI2(var_arg));
                        }
                        break;
 
                case VT_UI4:
-                       if(var_arg->vt & VT_BYREF)
+                       if(V_ISBYREF(var_arg))
                        {
-                               ZVAL_LONG(pval_arg, (long)*(var_arg->pulVal));
+                               ZVAL_LONG(pval_arg, (long)*V_UI4REF(var_arg));
                        }
                        else
                        {
-                               ZVAL_LONG(pval_arg, (long)var_arg->ulVal);
+                               ZVAL_LONG(pval_arg, (long)V_UI4(var_arg));
                        }
                        break;
 
                case VT_INT:
-                       if(var_arg->vt & VT_BYREF)
+                       if(V_ISBYREF(var_arg))
                        {
-                               ZVAL_LONG(pval_arg, (long)*(var_arg->pintVal));
+                               ZVAL_LONG(pval_arg, (long)*V_INTREF(var_arg));
                        }
                        else
                        {
-                               ZVAL_LONG(pval_arg, (long)var_arg->intVal);
+                               ZVAL_LONG(pval_arg, (long)V_INT(var_arg));
                        }
                        break;
 
                case VT_UINT:
-                       if(var_arg->vt & VT_BYREF)
+                       if(V_ISBYREF(var_arg))
                        {
-                               ZVAL_LONG(pval_arg, (long)*(var_arg->puintVal));
+                               ZVAL_LONG(pval_arg, (long)*V_UINTREF(var_arg));
                        }
                        else
                        {
-                               ZVAL_LONG(pval_arg, (long)var_arg->uintVal);
+                               ZVAL_LONG(pval_arg, (long)V_UINT(var_arg));
                        }
                        break;
 
                default:
-                       php_error(E_WARNING,"Unsupported variant type: %d (0x%X)", var_arg->vt, var_arg->vt);
+                       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;