示例#1
0
/* map an ID to a name */
HRESULT php_com_get_id_of_name(php_com_dotnet_object *obj, char *name,
		size_t namelen, DISPID *dispid)
{
	OLECHAR *olename;
	HRESULT hr;
	zval *tmp;

	if (namelen == -1) {
		namelen = strlen(name);
	}

	if (obj->id_of_name_cache && NULL != (tmp = zend_hash_str_find(obj->id_of_name_cache, name, namelen))) {
		*dispid = (DISPID)Z_LVAL_P(tmp);
		return S_OK;
	}
	
	olename = php_com_string_to_olestring(name, namelen, obj->code_page);

	if (obj->typeinfo) {
		hr = ITypeInfo_GetIDsOfNames(obj->typeinfo, &olename, 1, dispid);
		if (FAILED(hr)) {
			hr = IDispatch_GetIDsOfNames(V_DISPATCH(&obj->v), &IID_NULL, &olename, 1, LOCALE_SYSTEM_DEFAULT, dispid);
			if (SUCCEEDED(hr)) {
				/* fall back on IDispatch direct */
				ITypeInfo_Release(obj->typeinfo);
				obj->typeinfo = NULL;
			}
		}
	} else {
		hr = IDispatch_GetIDsOfNames(V_DISPATCH(&obj->v), &IID_NULL, &olename, 1, LOCALE_SYSTEM_DEFAULT, dispid);
	}
	efree(olename);

	if (SUCCEEDED(hr)) {
		zval tmp;

		/* cache the mapping */
		if (!obj->id_of_name_cache) {
			ALLOC_HASHTABLE(obj->id_of_name_cache);
			zend_hash_init(obj->id_of_name_cache, 2, NULL, NULL, 0);
		}
		ZVAL_LONG(&tmp, *dispid);
		zend_hash_str_update(obj->id_of_name_cache, name, namelen, &tmp);
	}
	
	return hr;
}
示例#2
0
/* The search string can be either:
 * a) a file name
 * b) a CLSID, major, minor e.g. "{00000200-0000-0010-8000-00AA006D2EA4},2,0"
 * c) a Type Library name e.g. "Microsoft OLE DB ActiveX Data Objects 1.0 Library"
 */
PHP_COM_DOTNET_API ITypeLib *php_com_load_typelib(char *search_string, int codepage TSRMLS_DC)
{
	ITypeLib *TL = NULL;
	char *strtok_buf, *major, *minor;
	CLSID clsid;
	OLECHAR *p;
	HRESULT hr;

	search_string = php_strtok_r(search_string, ",", &strtok_buf);

	if (search_string == NULL) {
		return NULL;
	}

	major = php_strtok_r(NULL, ",", &strtok_buf);
	minor = php_strtok_r(NULL, ",", &strtok_buf);

	p = php_com_string_to_olestring(search_string, strlen(search_string), codepage TSRMLS_CC);

	if (SUCCEEDED(CLSIDFromString(p, &clsid))) {
		WORD major_i = 1, minor_i = 0;

		/* pick up the major/minor numbers; if none specified, default to 1,0 */
		if (major && minor) {
			major_i = (WORD)atoi(major);
			minor_i = (WORD)atoi(minor);
		}

		/* Load the TypeLib by GUID */
		hr = LoadRegTypeLib((REFGUID)&clsid, major_i, minor_i, LANG_NEUTRAL, &TL);

		/* if that failed, assumed that the GUID is actually a CLSID and
		 * attemp to get the library via an instance of that class */
		if (FAILED(hr) && (major == NULL || minor == NULL)) {
			IDispatch *disp = NULL;
			ITypeInfo *info = NULL;
			int idx;

			if (SUCCEEDED(hr = CoCreateInstance(&clsid, NULL, CLSCTX_SERVER, &IID_IDispatch, (LPVOID*)&disp)) &&
					SUCCEEDED(hr = IDispatch_GetTypeInfo(disp, 0, LANG_NEUTRAL, &info))) {
				hr = ITypeInfo_GetContainingTypeLib(info, &TL, &idx);
			}

			if (info) {
				ITypeInfo_Release(info);
			}
			if (disp) {
				IDispatch_Release(disp);
			}
		}
	} else {
		/* Try to load it from a file; if it fails, do a really painful search of
		 * the registry */
		if (FAILED(LoadTypeLib(p, &TL))) {
			HKEY hkey, hsubkey;
			DWORD SubKeys, MaxSubKeyLength;
			char *keyname;
			unsigned int i, j;
			DWORD VersionCount;
			char version[20];
			char *libname;
			DWORD libnamelen;

			if (ERROR_SUCCESS == RegOpenKeyEx(HKEY_CLASSES_ROOT, "TypeLib", 0, KEY_READ, &hkey) &&
					ERROR_SUCCESS == RegQueryInfoKey(hkey, NULL, NULL, NULL, &SubKeys,
					&MaxSubKeyLength, NULL, NULL, NULL, NULL, NULL, NULL)) {

				MaxSubKeyLength++; /* make room for NUL */
				keyname = emalloc(MaxSubKeyLength);
				libname = emalloc(strlen(search_string) + 1);

				for (i = 0; i < SubKeys && TL == NULL; i++) {
					if (ERROR_SUCCESS == RegEnumKey(hkey, i, keyname, MaxSubKeyLength) &&
							ERROR_SUCCESS == RegOpenKeyEx(hkey, keyname, 0, KEY_READ, &hsubkey)) {
						if (ERROR_SUCCESS == RegQueryInfoKey(hsubkey, NULL, NULL, NULL, &VersionCount,
								NULL, NULL, NULL, NULL, NULL, NULL, NULL)) {
							for (j = 0; j < VersionCount; j++) {
								if (ERROR_SUCCESS != RegEnumKey(hsubkey, j, version, sizeof(version))) {
									continue;
								}
								/* get the default value for this key and compare */
								libnamelen = strlen(search_string)+1;
								if (ERROR_SUCCESS == RegQueryValue(hsubkey, version, libname, &libnamelen)) {
									if (0 == stricmp(libname, search_string)) {
										char *str = NULL;
										int major_tmp, minor_tmp;

										/* fetch the GUID and add the version numbers */
										if (2 != sscanf(version, "%d.%d", &major_tmp, &minor_tmp)) {
											major_tmp = 1;
											minor_tmp = 0;
										}
										spprintf(&str, 0, "%s,%d,%d", keyname, major_tmp, minor_tmp);
										/* recurse */
										TL = php_com_load_typelib(str, codepage TSRMLS_CC);

										efree(str);
										break;
									}
								}
							}
						}
						RegCloseKey(hsubkey);
					}
				}
				RegCloseKey(hkey);
				efree(keyname);
				efree(libname);
			}
		}
	}
	
	efree(p);

	return TL;
}
示例#3
0
ITypeInfo *php_com_locate_typeinfo(char *typelibname, php_com_dotnet_object *obj, char *dispname, int sink)
{
	ITypeInfo *typeinfo = NULL;
	ITypeLib *typelib = NULL;
	int gotguid = 0;
	GUID iid;

	if (obj) {
		if (dispname == NULL && sink) {
			IProvideClassInfo2 *pci2;
			IProvideClassInfo *pci;

			if (SUCCEEDED(IDispatch_QueryInterface(V_DISPATCH(&obj->v), &IID_IProvideClassInfo2, (void**)&pci2))) {
				gotguid = SUCCEEDED(IProvideClassInfo2_GetGUID(pci2, GUIDKIND_DEFAULT_SOURCE_DISP_IID, &iid));
				IProvideClassInfo2_Release(pci2);
			}
			if (!gotguid && SUCCEEDED(IDispatch_QueryInterface(V_DISPATCH(&obj->v), &IID_IProvideClassInfo, (void**)&pci))) {
				/* examine the available interfaces */
				/* TODO: write some code here */
				php_error_docref(NULL, E_WARNING, "IProvideClassInfo: this code not yet written!");
				IProvideClassInfo_Release(pci);
			}
		} else if (dispname == NULL) {
			if (obj->typeinfo) {
				ITypeInfo_AddRef(obj->typeinfo);
				return obj->typeinfo;
			} else {
				IDispatch_GetTypeInfo(V_DISPATCH(&obj->v), 0, LANG_NEUTRAL, &typeinfo);
				if (typeinfo) {
					return typeinfo;
				}
			}
		} else if (dispname && obj->typeinfo) {
			unsigned int idx;
			/* get the library from the object; the rest will be dealt with later */
			ITypeInfo_GetContainingTypeLib(obj->typeinfo, &typelib, &idx);
		} else if (typelibname == NULL) {
			IDispatch_GetTypeInfo(V_DISPATCH(&obj->v), 0, LANG_NEUTRAL, &typeinfo);
			if (dispname) {
				unsigned int idx;
				/* get the library from the object; the rest will be dealt with later */
				ITypeInfo_GetContainingTypeLib(typeinfo, &typelib, &idx);

				if (typelib) {
					ITypeInfo_Release(typeinfo);
					typeinfo = NULL;
				}
			}
		}
	} else if (typelibname) {
		/* Fetch the typelibrary and use that to look things up */
		typelib = php_com_load_typelib(typelibname, CP_THREAD_ACP);
	}

	if (!gotguid && dispname && typelib) {
		unsigned short cfound;
		MEMBERID memid;
		OLECHAR *olename = php_com_string_to_olestring(dispname, strlen(dispname), CP_ACP);

		cfound = 1;
		if (FAILED(ITypeLib_FindName(typelib, olename, 0, &typeinfo, &memid, &cfound)) || cfound == 0) {
			CLSID coclass;
			ITypeInfo *coinfo;

			/* assume that it might be a progid instead */
			if (SUCCEEDED(CLSIDFromProgID(olename, &coclass)) &&
					SUCCEEDED(ITypeLib_GetTypeInfoOfGuid(typelib, &coclass, &coinfo))) {

				/* enumerate implemented interfaces and pick the one as indicated by sink */
				TYPEATTR *attr;
				int i;

				ITypeInfo_GetTypeAttr(coinfo, &attr);

				for (i = 0; i < attr->cImplTypes; i++) {
					HREFTYPE rt;
					int tf;

					if (FAILED(ITypeInfo_GetImplTypeFlags(coinfo, i, &tf))) {
						continue;
					}

					if ((sink && tf == (IMPLTYPEFLAG_FSOURCE|IMPLTYPEFLAG_FDEFAULT)) ||
						(!sink && (tf & IMPLTYPEFLAG_FSOURCE) == 0)) {

						/* flags match what we are looking for */

						if (SUCCEEDED(ITypeInfo_GetRefTypeOfImplType(coinfo, i, &rt)))
							if (SUCCEEDED(ITypeInfo_GetRefTypeInfo(coinfo, rt, &typeinfo)))
								break;

					}
				}

				ITypeInfo_ReleaseTypeAttr(coinfo, attr);
				ITypeInfo_Release(coinfo);
			}
		}


		efree(olename);
	} else if (gotguid) {
		ITypeLib_GetTypeInfoOfGuid(typelib, &iid, &typeinfo);
	}

	if (typelib) {
		ITypeLib_Release(typelib);
	}

	return typeinfo;
}
示例#4
0
PHP_COM_DOTNET_API void php_com_variant_from_zval(VARIANT *v, zval *z, int codepage TSRMLS_DC)
{
	OLECHAR *olestring;
	php_com_dotnet_object *obj;
	
	switch (Z_TYPE_P(z)) {
		case IS_NULL:
			V_VT(v) = VT_NULL;
			break;

		case IS_BOOL:
			V_VT(v) = VT_BOOL;
			V_BOOL(v) = Z_BVAL_P(z) ? VARIANT_TRUE : VARIANT_FALSE;
			break;

		case IS_OBJECT:
			if (php_com_is_valid_object(z TSRMLS_CC)) {
				obj = CDNO_FETCH(z);
				if (V_VT(&obj->v) == VT_DISPATCH) {
					/* pass the underlying object */
					V_VT(v) = VT_DISPATCH;
					if (V_DISPATCH(&obj->v)) {
						IDispatch_AddRef(V_DISPATCH(&obj->v));
					}
					V_DISPATCH(v) = V_DISPATCH(&obj->v);
				} else {
					/* pass the variant by reference */
					V_VT(v) = VT_VARIANT | VT_BYREF;
					V_VARIANTREF(v) = &obj->v;
				}
			} else {
				/* export the PHP object using our COM wrapper */
				V_VT(v) = VT_DISPATCH;
				V_DISPATCH(v) = php_com_wrapper_export(z TSRMLS_CC);
			}
			break;
			
		case IS_ARRAY:
			/* map as safe array */
			safe_array_from_zval(v, z, codepage TSRMLS_CC);
			break;

		case IS_LONG:
			V_VT(v) = VT_I4;
			V_I4(v) = Z_LVAL_P(z);
			break;

		case IS_DOUBLE:
			V_VT(v) = VT_R8;
			V_R8(v) = Z_DVAL_P(z);
			break;

		case IS_STRING:
			V_VT(v) = VT_BSTR;
			olestring = php_com_string_to_olestring(Z_STRVAL_P(z), Z_STRLEN_P(z), codepage TSRMLS_CC);
			V_BSTR(v) = SysAllocStringByteLen((char*)olestring, Z_STRLEN_P(z) * sizeof(OLECHAR));
			efree(olestring);
			break;

		case IS_RESOURCE:
		case IS_CONSTANT:
		case IS_CONSTANT_ARRAY:
		default:
			V_VT(v) = VT_NULL;
			break;
	}
}
示例#5
0
static union _zend_function *com_method_get(zend_object **object_ptr, zend_string *name, const zval *key)
{
	zend_internal_function f, *fptr = NULL;
	union _zend_function *func;
	DISPID dummy;
	php_com_dotnet_object *obj = (php_com_dotnet_object*)*object_ptr;

	if (V_VT(&obj->v) != VT_DISPATCH) {
		return NULL;
	}

	if (FAILED(php_com_get_id_of_name(obj, name->val, name->len, &dummy))) {
		return NULL;
	}

	/* check cache */
	if (obj->method_cache == NULL || NULL == (fptr = zend_hash_find_ptr(obj->method_cache, name))) {
		f.type = ZEND_OVERLOADED_FUNCTION;
		f.num_args = 0;
		f.arg_info = NULL;
		f.scope = obj->ce;
		f.fn_flags = ZEND_ACC_CALL_VIA_HANDLER;
		f.function_name = zend_string_copy(name);
		f.handler = PHP_FN(com_method_handler);

		fptr = &f;

		if (obj->typeinfo) {
			/* look for byref params */
			ITypeComp *comp;
			ITypeInfo *TI = NULL;
			DESCKIND kind;
			BINDPTR bindptr;
			OLECHAR *olename;
			ULONG lhash;
			int i;

			if (SUCCEEDED(ITypeInfo_GetTypeComp(obj->typeinfo, &comp))) {
				olename = php_com_string_to_olestring(name->val, name->len, obj->code_page);
				lhash = LHashValOfNameSys(SYS_WIN32, LOCALE_SYSTEM_DEFAULT, olename);

				if (SUCCEEDED(ITypeComp_Bind(comp, olename, lhash, INVOKE_FUNC, &TI, &kind, &bindptr))) {
					switch (kind) {
						case DESCKIND_FUNCDESC:
							f.arg_info = ecalloc(bindptr.lpfuncdesc->cParams, sizeof(zend_arg_info));

							for (i = 0; i < bindptr.lpfuncdesc->cParams; i++) {
								f.arg_info[i].allow_null = 1;
								if (bindptr.lpfuncdesc->lprgelemdescParam[i].paramdesc.wParamFlags & PARAMFLAG_FOUT) {
									f.arg_info[i].pass_by_reference = ZEND_SEND_BY_REF;
								}
							}

							f.num_args = bindptr.lpfuncdesc->cParams;

							ITypeInfo_ReleaseFuncDesc(TI, bindptr.lpfuncdesc);
							break;

							/* these should not happen, but *might* happen if the user
							 * screws up; lets avoid a leak in that case */
						case DESCKIND_VARDESC:
							ITypeInfo_ReleaseVarDesc(TI, bindptr.lpvardesc);
							break;
						case DESCKIND_TYPECOMP:
							ITypeComp_Release(bindptr.lptcomp);
							break;

						case DESCKIND_NONE:
							break;
					}
					if (TI) {
						ITypeInfo_Release(TI);
					}
				}
				ITypeComp_Release(comp);
				efree(olename);
			}
		}

		zend_set_function_arg_flags((zend_function*)&f);
		/* save this method in the cache */
		if (!obj->method_cache) {
			ALLOC_HASHTABLE(obj->method_cache);
			zend_hash_init(obj->method_cache, 2, NULL, function_dtor, 0);
		}

		zend_hash_update_mem(obj->method_cache, name, &f, sizeof(f));
	}

	if (fptr) {
		/* duplicate this into a new chunk of emalloc'd memory,
		 * since the engine will efree it */
		func = emalloc(sizeof(*fptr));
		memcpy(func, fptr, sizeof(*fptr));

		return func;
	}

	return NULL;
}
示例#6
0
PHP_COM_DOTNET_API void php_com_variant_from_zval(VARIANT *v, zval *z, int codepage)
{
	OLECHAR *olestring;
	php_com_dotnet_object *obj;
	zend_uchar ztype = IS_NULL;

	if (z) {
		ZVAL_DEREF(z);
		ztype = Z_TYPE_P(z);
	}

	switch (ztype) {
		case IS_NULL:
			V_VT(v) = VT_NULL;
			break;

		case IS_FALSE:
			V_VT(v) = VT_BOOL;
			V_BOOL(v) = VARIANT_FALSE;
			break;

		case IS_TRUE:
			V_VT(v) = VT_BOOL;
			V_BOOL(v) = VARIANT_TRUE;
			break;

		case IS_OBJECT:
			if (php_com_is_valid_object(z)) {
				obj = CDNO_FETCH(z);
				if (V_VT(&obj->v) == VT_DISPATCH) {
					/* pass the underlying object */
					V_VT(v) = VT_DISPATCH;
					if (V_DISPATCH(&obj->v)) {
						IDispatch_AddRef(V_DISPATCH(&obj->v));
					}
					V_DISPATCH(v) = V_DISPATCH(&obj->v);
				} else {
					/* pass the variant by reference */
					V_VT(v) = VT_VARIANT | VT_BYREF;
					V_VARIANTREF(v) = &obj->v;
				}
			} else {
				/* export the PHP object using our COM wrapper */
				V_VT(v) = VT_DISPATCH;
				V_DISPATCH(v) = php_com_wrapper_export(z);
			}
			break;

		case IS_ARRAY:
			/* map as safe array */
			safe_array_from_zval(v, z, codepage);
			break;

		case IS_LONG:
#if SIZEOF_ZEND_LONG == 4
			V_VT(v) = VT_I4;
			V_I4(v) = Z_LVAL_P(z);
#else
			V_VT(v) = VT_I8;
			V_I8(v) = Z_LVAL_P(z);
#endif
			break;

		case IS_DOUBLE:
			V_VT(v) = VT_R8;
			V_R8(v) = Z_DVAL_P(z);
			break;

		case IS_STRING:
			V_VT(v) = VT_BSTR;
			olestring = php_com_string_to_olestring(Z_STRVAL_P(z), Z_STRLEN_P(z), codepage);
			if (CP_UTF8 == codepage) {
				V_BSTR(v) = SysAllocStringByteLen((char*)olestring, (UINT)(wcslen(olestring) * sizeof(OLECHAR)));
			} else {
				V_BSTR(v) = SysAllocStringByteLen((char*)olestring, (UINT)(Z_STRLEN_P(z) * sizeof(OLECHAR)));
			}
			efree(olestring);
			break;

		case IS_RESOURCE:
		case IS_CONSTANT_AST:
		default:
			V_VT(v) = VT_NULL;
			break;
	}
}