static void test_TypeComp(void) { ITypeLib *pTypeLib; ITypeComp *pTypeComp; HRESULT hr; ULONG ulHash; DESCKIND desckind; BINDPTR bindptr; ITypeInfo *pTypeInfo; ITypeInfo *pFontTypeInfo; static WCHAR wszStdFunctions[] = {'S','t','d','F','u','n','c','t','i','o','n','s',0}; static WCHAR wszSavePicture[] = {'S','a','v','e','P','i','c','t','u','r','e',0}; static WCHAR wszOLE_TRISTATE[] = {'O','L','E','_','T','R','I','S','T','A','T','E',0}; static WCHAR wszUnchecked[] = {'U','n','c','h','e','c','k','e','d',0}; static WCHAR wszIUnknown[] = {'I','U','n','k','n','o','w','n',0}; static WCHAR wszFont[] = {'F','o','n','t',0}; static WCHAR wszGUID[] = {'G','U','I','D',0}; static WCHAR wszStdPicture[] = {'S','t','d','P','i','c','t','u','r','e',0}; static WCHAR wszOLE_COLOR[] = {'O','L','E','_','C','O','L','O','R',0}; static WCHAR wszClone[] = {'C','l','o','n','e',0}; static WCHAR wszclone[] = {'c','l','o','n','e',0}; hr = LoadTypeLib(wszStdOle2, &pTypeLib); ok_ole_success(hr, LoadTypeLib); hr = ITypeLib_GetTypeComp(pTypeLib, &pTypeComp); ok_ole_success(hr, ITypeLib_GetTypeComp); /* test getting a TKIND_MODULE */ ulHash = LHashValOfNameSys(SYS_WIN32, LOCALE_NEUTRAL, wszStdFunctions); hr = ITypeComp_Bind(pTypeComp, wszStdFunctions, ulHash, 0, &pTypeInfo, &desckind, &bindptr); ok_ole_success(hr, ITypeComp_Bind); ok(desckind == DESCKIND_TYPECOMP, "desckind should have been DESCKIND_TYPECOMP instead of %d\n", desckind); ok(!pTypeInfo, "pTypeInfo should have been set to NULL\n"); ITypeComp_Release(bindptr.lptcomp); /* test getting a TKIND_MODULE with INVOKE_PROPERTYGET */ ulHash = LHashValOfNameSys(SYS_WIN32, LOCALE_NEUTRAL, wszStdFunctions); hr = ITypeComp_Bind(pTypeComp, wszStdFunctions, ulHash, INVOKE_PROPERTYGET, &pTypeInfo, &desckind, &bindptr); ok_ole_success(hr, ITypeComp_Bind); ok(desckind == DESCKIND_TYPECOMP, "desckind should have been DESCKIND_TYPECOMP instead of %d\n", desckind); ok(!pTypeInfo, "pTypeInfo should have been set to NULL\n"); ITypeComp_Release(bindptr.lptcomp); /* test getting a function within a TKIND_MODULE */ ulHash = LHashValOfNameSys(SYS_WIN32, LOCALE_NEUTRAL, wszSavePicture); hr = ITypeComp_Bind(pTypeComp, wszSavePicture, ulHash, 0, &pTypeInfo, &desckind, &bindptr); ok_ole_success(hr, ITypeComp_Bind); ok(desckind == DESCKIND_FUNCDESC, "desckind should have been DESCKIND_FUNCDESC instead of %d\n", desckind); ok(bindptr.lpfuncdesc != NULL, "bindptr.lpfuncdesc should not have been set to NULL\n"); ITypeInfo_ReleaseFuncDesc(pTypeInfo, bindptr.lpfuncdesc); ITypeInfo_Release(pTypeInfo); /* test getting a function within a TKIND_MODULE with INVOKE_PROPERTYGET */ ulHash = LHashValOfNameSys(SYS_WIN32, LOCALE_NEUTRAL, wszSavePicture); hr = ITypeComp_Bind(pTypeComp, wszSavePicture, ulHash, INVOKE_PROPERTYGET, &pTypeInfo, &desckind, &bindptr); todo_wine ok(hr == TYPE_E_TYPEMISMATCH, "ITypeComp_Bind should have failed with TYPE_E_TYPEMISMATCH instead of 0x%08x\n", hr); ok(desckind == DESCKIND_NONE, "desckind should have been DESCKIND_NONE instead of %d\n", desckind); ok(!pTypeInfo, "pTypeInfo should have been set to NULL\n"); ok(!bindptr.lptcomp, "bindptr should have been set to NULL\n"); /* test getting a TKIND_ENUM */ ulHash = LHashValOfNameSys(SYS_WIN32, LOCALE_NEUTRAL, wszOLE_TRISTATE); hr = ITypeComp_Bind(pTypeComp, wszOLE_TRISTATE, ulHash, 0, &pTypeInfo, &desckind, &bindptr); ok_ole_success(hr, ITypeComp_Bind); ok(desckind == DESCKIND_TYPECOMP, "desckind should have been DESCKIND_TYPECOMP instead of %d\n", desckind); ok(!pTypeInfo, "pTypeInfo should have been set to NULL\n"); ITypeComp_Release(bindptr.lptcomp); /* test getting a value within a TKIND_ENUM */ ulHash = LHashValOfNameSys(SYS_WIN32, LOCALE_NEUTRAL, wszUnchecked); hr = ITypeComp_Bind(pTypeComp, wszUnchecked, ulHash, 0, &pTypeInfo, &desckind, &bindptr); ok_ole_success(hr, ITypeComp_Bind); ok(desckind == DESCKIND_VARDESC, "desckind should have been DESCKIND_VARDESC instead of %d\n", desckind); ITypeInfo_ReleaseVarDesc(pTypeInfo, bindptr.lpvardesc); ITypeInfo_Release(pTypeInfo); /* test getting a TKIND_INTERFACE */ ulHash = LHashValOfNameSys(SYS_WIN32, LOCALE_NEUTRAL, wszIUnknown); hr = ITypeComp_Bind(pTypeComp, wszIUnknown, ulHash, 0, &pTypeInfo, &desckind, &bindptr); ok_ole_success(hr, ITypeComp_Bind); ok(desckind == DESCKIND_NONE, "desckind should have been DESCKIND_NONE instead of %d\n", desckind); ok(!pTypeInfo, "pTypeInfo should have been set to NULL\n"); ok(!bindptr.lptcomp, "bindptr should have been set to NULL\n"); /* test getting a TKIND_DISPATCH */ ulHash = LHashValOfNameSys(SYS_WIN32, LOCALE_NEUTRAL, wszFont); hr = ITypeComp_Bind(pTypeComp, wszFont, ulHash, 0, &pTypeInfo, &desckind, &bindptr); ok_ole_success(hr, ITypeComp_Bind); ok(desckind == DESCKIND_NONE, "desckind should have been DESCKIND_NONE instead of %d\n", desckind); ok(!pTypeInfo, "pTypeInfo should have been set to NULL\n"); ok(!bindptr.lptcomp, "bindptr should have been set to NULL\n"); /* test getting a TKIND_RECORD/TKIND_ALIAS */ ulHash = LHashValOfNameSys(SYS_WIN32, LOCALE_NEUTRAL, wszGUID); hr = ITypeComp_Bind(pTypeComp, wszGUID, ulHash, 0, &pTypeInfo, &desckind, &bindptr); ok_ole_success(hr, ITypeComp_Bind); ok(desckind == DESCKIND_NONE, "desckind should have been DESCKIND_NONE instead of %d\n", desckind); ok(!pTypeInfo, "pTypeInfo should have been set to NULL\n"); ok(!bindptr.lptcomp, "bindptr should have been set to NULL\n"); /* test getting a TKIND_ALIAS */ ulHash = LHashValOfNameSys(SYS_WIN32, LOCALE_NEUTRAL, wszOLE_COLOR); hr = ITypeComp_Bind(pTypeComp, wszOLE_COLOR, ulHash, 0, &pTypeInfo, &desckind, &bindptr); ok_ole_success(hr, ITypeComp_Bind); ok(desckind == DESCKIND_NONE, "desckind should have been DESCKIND_NONE instead of %d\n", desckind); ok(!pTypeInfo, "pTypeInfo should have been set to NULL\n"); ok(!bindptr.lptcomp, "bindptr should have been set to NULL\n"); /* test getting a TKIND_COCLASS */ ulHash = LHashValOfNameSys(SYS_WIN32, LOCALE_NEUTRAL, wszStdPicture); hr = ITypeComp_Bind(pTypeComp, wszStdPicture, ulHash, 0, &pTypeInfo, &desckind, &bindptr); ok_ole_success(hr, ITypeComp_Bind); ok(desckind == DESCKIND_NONE, "desckind should have been DESCKIND_NONE instead of %d\n", desckind); ok(!pTypeInfo, "pTypeInfo should have been set to NULL\n"); ok(!bindptr.lptcomp, "bindptr should have been set to NULL\n"); ITypeComp_Release(pTypeComp); /* tests for ITypeComp on an interface */ hr = ITypeLib_GetTypeInfoOfGuid(pTypeLib, &IID_IFont, &pFontTypeInfo); ok_ole_success(hr, ITypeLib_GetTypeInfoOfGuid); hr = ITypeInfo_GetTypeComp(pFontTypeInfo, &pTypeComp); ok_ole_success(hr, ITypeLib_GetTypeComp); ulHash = LHashValOfNameSys(SYS_WIN32, LOCALE_NEUTRAL, wszClone); hr = ITypeComp_Bind(pTypeComp, wszClone, ulHash, 0, &pTypeInfo, &desckind, &bindptr); ok_ole_success(hr, ITypeComp_Bind); ok(desckind == DESCKIND_FUNCDESC, "desckind should have been DESCKIND_FUNCDESC instead of %d\n", desckind); ok(bindptr.lpfuncdesc != NULL, "bindptr.lpfuncdesc should not have been set to NULL\n"); ITypeInfo_ReleaseFuncDesc(pTypeInfo, bindptr.lpfuncdesc); ITypeInfo_Release(pTypeInfo); ulHash = LHashValOfNameSys(SYS_WIN32, LOCALE_NEUTRAL, wszClone); hr = ITypeComp_Bind(pTypeComp, wszClone, ulHash, INVOKE_PROPERTYGET, &pTypeInfo, &desckind, &bindptr); ok(hr == TYPE_E_TYPEMISMATCH, "ITypeComp_Bind should have failed with TYPE_E_TYPEMISMATCH instead of 0x%08x\n", hr); ok(desckind == DESCKIND_NONE, "desckind should have been DESCKIND_NONE instead of %d\n", desckind); ok(!pTypeInfo, "pTypeInfo should have been set to NULL\n"); ok(!bindptr.lptcomp, "bindptr should have been set to NULL\n"); /* tests that the compare is case-insensitive */ ulHash = LHashValOfNameSys(SYS_WIN32, LOCALE_NEUTRAL, wszclone); hr = ITypeComp_Bind(pTypeComp, wszclone, ulHash, 0, &pTypeInfo, &desckind, &bindptr); ok_ole_success(hr, ITypeComp_Bind); ok(desckind == DESCKIND_FUNCDESC, "desckind should have been DESCKIND_FUNCDESC instead of %d\n", desckind); ok(bindptr.lpfuncdesc != NULL, "bindptr.lpfuncdesc should not have been set to NULL\n"); ITypeInfo_ReleaseFuncDesc(pTypeInfo, bindptr.lpfuncdesc); ITypeInfo_Release(pTypeInfo); ITypeComp_Release(pTypeComp); ITypeInfo_Release(pFontTypeInfo); ITypeLib_Release(pTypeLib); }
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; }