]> granicus.if.org Git - php/commitdiff
no message
authorHarald Radi <phanto@php.net>
Tue, 25 Sep 2001 23:39:50 +0000 (23:39 +0000)
committerHarald Radi <phanto@php.net>
Tue, 25 Sep 2001 23:39:50 +0000 (23:39 +0000)
ext/com/COM.c
ext/rpc/com/com_wrapper.c

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