internal ComMethodDesc(ITypeInfo typeInfo, FUNCDESC funcDesc) : this(funcDesc.memid) { InvokeKind = funcDesc.invkind; int cNames; string[] rgNames = new string[1 + funcDesc.cParams]; typeInfo.GetNames(DispId, rgNames, rgNames.Length, out cNames); bool skipLast = false; if (IsPropertyPut && rgNames[rgNames.Length - 1] == null) { rgNames[rgNames.Length - 1] = "value"; cNames++; skipLast = true; } Debug.Assert(cNames == rgNames.Length); _name = rgNames[0]; ParamCount = funcDesc.cParams; ReturnType = ComUtil.GetTypeFromTypeDesc(funcDesc.elemdescFunc.tdesc); ParameterInformation = ComUtil.GetParameterInformation(funcDesc, skipLast); }
protected void AddParams(FUNCDESC funcDesc, String[] names, int paramCount) { IntPtr elemPtr = funcDesc.lprgelemdescParam; for (int i = 0; i < paramCount; i++) { ELEMDESC elemDesc = (ELEMDESC)Marshal.PtrToStructure(elemPtr, typeof(ELEMDESC)); ComParamInfo pi = new ComParamInfo (names[i + 1], TypeLibUtil.TYPEDESCToString (_typeLib, _typeInfo, elemDesc.tdesc, TypeLibUtil.COMTYPE), elemDesc.desc.paramdesc.wParamFlags); _parameters.Add(pi); // Point to the next one elemPtr = new IntPtr(elemPtr.ToInt64() + Marshal.SizeOf(elemDesc)); } }
internal ComMethodDesc(ITypeInfo typeInfo, FUNCDESC funcDesc) : this(funcDesc.memid) { _hasTypeInfo = true; InvokeKind = funcDesc.invkind; int cNames; string[] rgNames = new string[1 + funcDesc.cParams]; typeInfo.GetNames(_memid, rgNames, rgNames.Length, out cNames); if (IsPropertyPut && rgNames[rgNames.Length - 1] == null) { rgNames[rgNames.Length - 1] = "value"; cNames++; } Debug.Assert(cNames == rgNames.Length); _name = rgNames[0]; _parameters = new ComParamDesc[funcDesc.cParams]; int offset = 0; for (int i = 0; i < funcDesc.cParams; i++) { ELEMDESC elemDesc = (ELEMDESC)Marshal.PtrToStructure( new IntPtr(funcDesc.lprgelemdescParam.ToInt64() + offset), typeof(ELEMDESC)); _parameters[i] = new ComParamDesc(ref elemDesc, rgNames[1 + i]); offset += Marshal.SizeOf(typeof(ELEMDESC)); } }
public void GetFuncDesc(int index, out IntPtr ppFuncDesc) { // Fail BEFORE allocating the handle to avoid leaks. If the real COM object fails in this method // and doesn't return the handle or clean it up itself there's not much we can do to avoid the leak. _faultInjector.FailurePointThrow(MockTypeLibrariesFailurePoints.ITypeInfo_GetFuncDesc); ppFuncDesc = _memoryHelper.AllocateHandle(Marshal.SizeOf <FUNCDESC>()); _memoryHelper.EnterSubAllocationScope(ppFuncDesc); FUNCDESC funcDesc = new FUNCDESC(); funcDesc.lprgelemdescParam = _memoryHelper.AllocateHandle(_definedFunctions[index].parameters.Length * Marshal.SizeOf <ELEMDESC>()); funcDesc.cParams = (short)_definedFunctions[index].parameters.Length; for (int i = 0; i < _definedFunctions[index].parameters.Length; i++) { ELEMDESC elemDesc = new ELEMDESC(); elemDesc.tdesc = _definedFunctions[index].parameters[i].CreateTypeDesc( new IntPtr(index * s_HREF_FUNCSPARAM_OFFSET_PERFUNC + i + s_HREF_FUNCSPARAM_OFFSET), _memoryHelper); Marshal.StructureToPtr( elemDesc, new IntPtr(funcDesc.lprgelemdescParam.ToInt64() + i * Marshal.SizeOf <ELEMDESC>()), false); } funcDesc.elemdescFunc.tdesc = _definedFunctions[index].returnType.CreateTypeDesc( new IntPtr(index + s_HREF_FUNCSRET_OFFSET), _memoryHelper); _memoryHelper.ExitSubAllocationScope(); Marshal.StructureToPtr(funcDesc, ppFuncDesc, false); }
protected void AddDomParams(FUNCDESC funcDesc, CodeMemberMethod meth, int limit) { IntPtr elemPtr = funcDesc.lprgelemdescParam; for (int i = 0; i < limit; i++) { ELEMDESC elemDesc = (ELEMDESC)Marshal.PtrToStructure(elemPtr, typeof(ELEMDESC)); ComParamInfo parameter = (ComParamInfo) _parameters[i]; String paramType = TypeLibUtil.TYPEDESCToString (_typeLib, _typeInfo, elemDesc.tdesc, !TypeLibUtil.COMTYPE); String paramInOut = null; if ((parameter._paramFlags & PARAMFLAG.PARAMFLAG_FIN) != 0) { paramInOut = "In"; } else if ((parameter._paramFlags & PARAMFLAG.PARAMFLAG_FOUT) != 0) { paramInOut = "Out"; // Ref becomes out for an output parameter if (paramType.StartsWith("ref ")) { paramType = "out " + paramType.Substring(4); } else { paramType = "out " + paramType; } } CodeParameterDeclarationExpression paramExpr = new CodeParameterDeclarationExpression (paramType, parameter._name); if (paramInOut != null) { paramExpr.CustomAttributes.Add (new CodeAttributeDeclaration ("System.Runtime.InteropServices." + paramInOut)); } meth.Parameters.Add(paramExpr); // Point to the next one elemPtr = new IntPtr(elemPtr.ToInt64() + Marshal.SizeOf(elemDesc)); } }
public unsafe MethodDesc(string name, string dll, string entryPoint, FUNCDESC funcdesc, string[] argumentNames, Func<uint, TypeDesc> typeFactory) { string tmpl = "___overloaded000"; if ((name.Length > tmpl.Length) && (name.IndexOf("___overloaded") == (name.Length - tmpl.Length))) name = name.Substring(0, name.Length - tmpl.Length); Name = EscapMethodName(name); Dll = dll; EntryPoint = entryPoint; Offset = funcdesc.oVft; ReturnValue = new ParameterDesc(funcdesc.elemdescFunc, string.Empty, typeFactory, 0, false, null); List<ParameterDesc> parameters = new List<ParameterDesc>(); for (int i = 0; i < funcdesc.cParams; i++) parameters.Add(new ParameterDesc(funcdesc.lprgelemdescParam[i], (i < argumentNames.Length) ? argumentNames[i] : "__arg" + i, typeFactory, 0, false, null)); Parameters = parameters.AsReadOnly(); //if (funcdesc.cParamsOpt != 0) // throw new Exception("Variable number of optional parameters is not supported"); //if (funcdesc.invkind != INVOKEKIND.INVOKE_FUNC) // throw new Exception("Only functions are currently supported"); if (funcdesc.cScodes >= 1) throw new Exception("Only one return value is supported"); switch (funcdesc.callconv) { case System.Runtime.InteropServices.ComTypes.CALLCONV.CC_CDECL: Convention = CallingConvention.Cdecl; break; case System.Runtime.InteropServices.ComTypes.CALLCONV.CC_STDCALL: Convention = CallingConvention.StdCall; break; default: throw new Exception("Calling convention " + funcdesc.callconv + " is not supported"); } switch (funcdesc.funckind) { case FUNCKIND.FUNC_DISPATCH: case FUNCKIND.FUNC_VIRTUAL: case FUNCKIND.FUNC_PUREVIRTUAL: case FUNCKIND.FUNC_NONVIRTUAL: case FUNCKIND.FUNC_STATIC: break; default: throw new Exception("Function kind " + funcdesc.funckind + " is not supported"); } }
internal ComMethodDesc(ITypeInfo typeInfo, FUNCDESC funcDesc) : this(funcDesc.memid) { _invokeKind = funcDesc.invkind; string[] rgNames = new string[1 + funcDesc.cParams]; typeInfo.GetNames(DispId, rgNames, rgNames.Length, out int cNames); if (IsPropertyPut && rgNames[rgNames.Length - 1] == null) { rgNames[rgNames.Length - 1] = "value"; cNames++; } Debug.Assert(cNames == rgNames.Length); Name = rgNames[0]; ParamCount = funcDesc.cParams; }
static void DealWithTypeInfo(UCOMITypeInfo it) { // Get the names from ITypeInfo string name; string docstring; Int32 ctxt; string helpfile; // TypeInfo name it.GetDocumentation(-1, out name, out docstring, out ctxt, out helpfile); IntPtr pa; it.GetTypeAttr(out pa); TYPEATTR ta = (TYPEATTR)Marshal.PtrToStructure(pa, typeof(TYPEATTR)); DealWithName(name, ta.guid); // Deal with funcs for (int i = 0; i < ta.cFuncs; i++) { IntPtr pfd; it.GetFuncDesc(i, out pfd); FUNCDESC fd = (FUNCDESC)Marshal.PtrToStructure(pfd, typeof(FUNCDESC)); it.GetDocumentation(fd.memid, out name, out docstring, out ctxt, out helpfile); DealWithName(name, Guid.Empty); } // Deal with vars for (int i = 0; i < ta.cVars; i++) { IntPtr pvd; it.GetVarDesc(i, out pvd); VARDESC vd = (VARDESC)Marshal.PtrToStructure(pvd, typeof(VARDESC)); it.GetDocumentation(vd.memid, out name, out docstring, out ctxt, out helpfile); DealWithName(name, Guid.Empty); } }
internal ComMemberInfo(BasicInfo parent, TYPEKIND typeKind, UCOMITypeInfo typeInfo, int index, bool dispatch, FUNCDESC funcDesc) : base(typeInfo) { int actLen; String[] memberNames = new String[100]; _typeInfo.GetNames(funcDesc.memid, memberNames, memberNames.Length, out actLen); _memberId = funcDesc.memid; // the high order part of the memberId is flags // for a dispatch interface if (dispatch) { _memberId &= 0xffff; // Make sure we get a 16 bit integer so that negative // DISPIDs show up correctly _memberId = (Int16)_memberId; } String docString; // Note, use the original unmasked memberId _typeInfo.GetDocumentation(funcDesc.memid, out _name, out docString, out _helpContext, out _helpFile); // Set using property so that nulls are checked DocString = docString; _parameters = new ArrayList(); _typeLib = parent.TypeLib; _index = index; _container = parent; _printName = _name; _nameKey = (String)_name; // Add the DISPID to the dispatch interfaces if (dispatch) { _dispatch = true; _printName += " - " + _memberId; } if (TraceUtil.If(this, TraceLevel.Verbose)) { Trace.WriteLine("MemberInfo: " + _name); } _type = TypeLibUtil.TYPEDESCToString (_typeLib, _typeInfo, funcDesc.elemdescFunc.tdesc, TypeLibUtil.COMTYPE); if (funcDesc.invkind == INVOKEKIND.INVOKE_FUNC) { _infoType = "Function"; _property = false; if (funcDesc.cParams > 0) { AddParams(funcDesc, memberNames, funcDesc.cParams); } } else { if (funcDesc.invkind == INVOKEKIND.INVOKE_PROPERTYGET) { _printName += " (get)"; _nameKey += NAMEKEY_GET; } else if (funcDesc.invkind == INVOKEKIND.INVOKE_PROPERTYPUT) { _printName += " (put)"; _nameKey += NAMEKEY_SET; } else if (funcDesc.invkind == INVOKEKIND.INVOKE_PROPERTYPUTREF) { _printName += " (put ref)"; _nameKey += NAMEKEY_SETREF; } _infoType = "Property"; _property = true; } _flagsString = FlagsString((FUNCFLAGS)funcDesc.wFuncFlags); if (_property) { _presInfo = PresentationMap. GetInfo(PresentationMap.COM_PROPERTY); } else { _presInfo = PresentationMap. GetInfo(PresentationMap.COM_METHOD); } }
/// <summary> /// Helper method for retrieving the function description structure for the given function index. /// This method needs to also return the native pointer to be released when we're done with our FUNCDESC. /// It's not really possible to copy everything to a managed struct and then release the ptr immediately /// here, since FUNCDESCs contain other native pointers we may need to access. /// </summary> internal static void GetFuncDescForDescIndex(ITypeInfo typeInfo, int funcIndex, out FUNCDESC funcDesc, out IntPtr funcDescHandle) { typeInfo.GetFuncDesc(funcIndex, out IntPtr pFuncDesc); // GetFuncDesc should never return null, this is just to be safe if (pFuncDesc == IntPtr.Zero) { throw new COMException( ResourceUtilities.GetResourceString("ResolveComReference.CannotRetrieveTypeInformation")); } funcDesc = (FUNCDESC)Marshal.PtrToStructure(pFuncDesc, typeof(FUNCDESC)); funcDescHandle = pFuncDesc; }
public FuncDesc(int index, ITypeInfo typeinfo) { m_typeinfo = typeinfo; m_ipFuncDesc = TypeLibResourceManager.GetDaemon().GetFuncDesc(typeinfo, index); m_funcdesc = (FUNCDESC)Marshal.PtrToStructure(m_ipFuncDesc, typeof(FUNCDESC)); }
/// <summary> /// Determines whether the name belongs to a COM property on the given raw COM object. /// </summary> /// <remarks> /// Looks up type information using the COM ITypeInfo interface. /// Caches the result in the object's built-in COM data area so that subsequent queries for the same name are fast. /// </remarks> /// <param name="obj"></param> /// <param name="memberName"></param> /// <returns>false if no type information is available, or for any error condition.</returns> /// internal static bool IsCOMProp(object obj, string memberName) { if (Utils.IsMono) { return(false); } // The memberName can be changed by the call to GetMemberDispID below (U to _ conversion), but we want // to cache the isComProp value for the unmodified member name, so we save it. string unmodifiedMemberName = memberName; object cachedValue = Marshal.GetComObjectData(obj, "NETLinkIsCOMProp" + unmodifiedMemberName); if (cachedValue != null) { return((bool)cachedValue); } else { UCOMIDispatch iDisp; UCOMITypeInfo iTypeInfo; try { iDisp = GetIDispatch(obj); iTypeInfo = GetITypeInfo(obj, iDisp); } catch (Exception) { Marshal.SetComObjectData(obj, "NETLinkIsCOMProp" + unmodifiedMemberName, false); return(false); } // GetMemberDispID() does not throw on failure--it returns -1. int memberDispId = GetMemberDispID(obj, iDisp, ref memberName); if (memberDispId == -1) { Marshal.SetComObjectData(obj, "NETLinkIsCOMProp" + unmodifiedMemberName, false); return(false); } // We have successfully passed GetIDsOfNames() and GetITypeInfo(), so we know that type info is available and that // the name is a member of the dispatch interface. The name may also have been modified to reflect U to _ conversion. // Previous versions of this method acquired an ITypeInfo2 from the ITypeInfo and called GetFuncIndexOfMemId() to get // a function index suitable for GetFuncDesc(). There were problems with that technique, in that the index returned // sometimes (not always) needed to have 7 added to it. Because we cache the T/F result from this method anyway, // we now just exhaustively call GetFuncDesc() on all the members, looking for one with the right memberDispId. // Then we can check its func info to see if it is a property with no args. bool result = false; IntPtr pTypeAttr; iTypeInfo.GetTypeAttr(out pTypeAttr); TYPEATTR typeAttr = (TYPEATTR)Marshal.PtrToStructure(pTypeAttr, typeof(TYPEATTR)); int numFuncs = typeAttr.cFuncs; iTypeInfo.ReleaseTypeAttr(pTypeAttr); for (int i = 0; i < numFuncs; i++) { IntPtr pFuncDesc; iTypeInfo.GetFuncDesc(i, out pFuncDesc); FUNCDESC funcDesc = (FUNCDESC)Marshal.PtrToStructure(pFuncDesc, typeof(FUNCDESC)); int thisMemberID = funcDesc.memid; INVOKEKIND invokeKind = funcDesc.invkind; int numParams = funcDesc.cParams; iTypeInfo.ReleaseFuncDesc(pFuncDesc); if (thisMemberID == memberDispId) { result = invokeKind == INVOKEKIND.INVOKE_PROPERTYGET && numParams == 0; break; } } Marshal.SetComObjectData(obj, "NETLinkIsCOMProp" + unmodifiedMemberName, result); return(result); } }
/// <summary> /// Gets parameter information for the given member. /// </summary> /// <remarks> /// Uses the COM ITypeInfo interface to get the information. Does not throw. If it returns false then the out params /// will not hold useful information. /// </remarks> /// <param name="obj"></param> /// <param name="memberName"></param> /// <param name="callType"></param> /// <param name="isBeingCalledWithZeroArgs"></param> /// <param name="paramTypes"></param> /// <param name="paramFlags"></param> /// <param name="endsWithParamArray"></param> /// <returns>true if the name refers to a valid member or if no type information is available</returns> /// internal static bool GetMemberInfo(object obj, ref string memberName, int callType, bool isBeingCalledWithZeroArgs, out Type[] paramTypes, out PARAMFLAG[] paramFlags, out bool endsWithParamArray) { // There are some early returns in this method, so we initialize the out params right away. To the caller, if these values // come back null it means that the information could not be determined. paramTypes = null; paramFlags = null; endsWithParamArray = false; int defaultLCID = GetUserDefaultLCID(); try { // Throws in this outer try cause true to be returned. They mean "type info could not be obtained, so the member is not // known to be invalid." UCOMIDispatch iDisp = GetIDispatch(obj); int memberDispId = GetMemberDispID(obj, iDisp, ref memberName); if (memberDispId == -1) { // Name not found by GetIDsOfNames. return(false); } // If no args are being passed, then we can skip all the machinations below about type info. if (isBeingCalledWithZeroArgs) { return(true); } UCOMITypeInfo iTypeInfo = GetITypeInfo(obj, iDisp); IntPtr pFuncDesc; // Check to see if the func index for this member name is already cached from a previous call. FuncIndexHolder fih = (FuncIndexHolder)Marshal.GetComObjectData(obj, "NETLinkFuncIndex" + memberName); if (fih == null) { // This will be populated below. fih = new FuncIndexHolder(); Marshal.SetComObjectData(obj, "NETLinkFuncIndex" + memberName, fih); } int funcIndex = -1; if (callType == Install.CALLTYPE_FIELD_OR_SIMPLE_PROP_GET) { if (fih.funcIndexForCALLTYPE_FIELD_OR_SIMPLE_PROP_GET != -1) { funcIndex = fih.funcIndexForCALLTYPE_FIELD_OR_SIMPLE_PROP_GET; } } else if (callType == Install.CALLTYPE_FIELD_OR_SIMPLE_PROP_SET || callType == Install.CALLTYPE_PARAM_PROP_SET) { if (fih.funcIndexForCALLTYPE_FIELD_OR_ANY_PROP_SET != -1) { funcIndex = fih.funcIndexForCALLTYPE_FIELD_OR_ANY_PROP_SET; } } else if (callType == Install.CALLTYPE_METHOD || callType == Install.CALLTYPE_PARAM_PROP_GET) { // COM objects are treated by M code as if they all have indexers, so calls like obj[1] will // come in as CALLTYPE_PARAM_PROP_GET with a property name of Item. We can just treat these like // method calls. if (fih.funcIndexForCALLTYPE_METHOD != -1) { funcIndex = fih.funcIndexForCALLTYPE_METHOD; } } // Did not have the func index for this call type cached. if (funcIndex == -1) { IntPtr pTypeAttr; iTypeInfo.GetTypeAttr(out pTypeAttr); TYPEATTR typeAttr = (TYPEATTR)Marshal.PtrToStructure(pTypeAttr, typeof(TYPEATTR)); int numFuncs = typeAttr.cFuncs; iTypeInfo.ReleaseTypeAttr(pTypeAttr); bool foundDispId = false; for (int thisIndex = 0; thisIndex < numFuncs; thisIndex++) { // Be aware that GetFuncDesc() can (I think) throw a cryptic "Element not found" exception, // such as for a hidden property like (Excel) _Application.ActiveDialog. iTypeInfo.GetFuncDesc(thisIndex, out pFuncDesc); FUNCDESC funcDesc = (FUNCDESC)Marshal.PtrToStructure(pFuncDesc, typeof(FUNCDESC)); int thisMemberId = funcDesc.memid; INVOKEKIND invokeKind = funcDesc.invkind; iTypeInfo.ReleaseFuncDesc(pFuncDesc); if (thisMemberId == memberDispId) { foundDispId = true; // Verify that it is a member of the correct call type. if (callType == Install.CALLTYPE_FIELD_OR_SIMPLE_PROP_GET && invokeKind == INVOKEKIND.INVOKE_PROPERTYGET) { fih.funcIndexForCALLTYPE_FIELD_OR_SIMPLE_PROP_GET = thisIndex; funcIndex = thisIndex; break; } else if ((callType == Install.CALLTYPE_FIELD_OR_SIMPLE_PROP_SET || callType == Install.CALLTYPE_PARAM_PROP_SET) && (invokeKind == INVOKEKIND.INVOKE_PROPERTYPUT || invokeKind == INVOKEKIND.INVOKE_PROPERTYPUTREF)) { fih.funcIndexForCALLTYPE_FIELD_OR_ANY_PROP_SET = thisIndex; funcIndex = thisIndex; break; } else if ((callType == Install.CALLTYPE_METHOD && (invokeKind == INVOKEKIND.INVOKE_FUNC || invokeKind == INVOKEKIND.INVOKE_PROPERTYGET)) || (callType == Install.CALLTYPE_PARAM_PROP_GET && invokeKind == INVOKEKIND.INVOKE_PROPERTYGET)) { // Parameterized prop gets, not sets, look like CALLTYPE_METHOD. Also, as discussed in an earlier comment, // indexer notation calls (obj[1]) are supported for all COM objects and come in as CALLTYPE_PARAM_PROP_GET. fih.funcIndexForCALLTYPE_METHOD = thisIndex; funcIndex = thisIndex; break; } } } if (funcIndex == -1) { // We didn't find the member in our search. This can happen in two ways. First, the member might // exist but not be the right call type. For this case we want to return false. Second, we didn't // even find the dispid. This can happen in unusual cases I don't understan An example of this // is the IWebBrowser2 interface obtained by CreateCOMObject["InternetExplorer.Application"]. // For this case we want to return true, as if there was no type info at all available, so the // call can still proceed. return(!foundDispId); } } // If we get to here, we have a valid funcIndex and memberDispId, and the member is of the correct variety // that corresponds to how it was called (e.g., it's a method and it was called as such). All that // remains is to get the parameter types. iTypeInfo.GetFuncDesc(funcIndex, out pFuncDesc); try { FUNCDESC funcDesc = (FUNCDESC)Marshal.PtrToStructure(pFuncDesc, typeof(FUNCDESC)); Debug.Assert(funcDesc.memid == memberDispId); int paramCount = funcDesc.cParams; // Functions that end with a VB-style ParamArray (a variable-length argument sequence) have -1 for the // cParamsOpt member. It is convenient to treat them specially, hence the 'endsWithParamArray' variable // (which is an out param for this method). The special treatment involves leaving the ParamArray arg off // the list of paramFlags and paramTypes. We just pretend there is one less arg to the function but // record that it ends with a ParamArray. We always know the type of this arg anyway: ByRef Variant[]. // To the caller, though, the individual args are sent as a sequence, not packed into an array. endsWithParamArray = funcDesc.cParamsOpt == -1; if (endsWithParamArray) { paramCount--; } paramTypes = new Type[paramCount]; paramFlags = new PARAMFLAG[paramCount]; IntPtr pElemDescArray = funcDesc.lprgelemdescParam; for (int paramIndex = 0; paramIndex < paramCount; paramIndex++) { ELEMDESC elemDesc = (ELEMDESC)Marshal.PtrToStructure((IntPtr)(pElemDescArray.ToInt64() + paramIndex * Marshal.SizeOf(typeof(ELEMDESC))), typeof(ELEMDESC)); TYPEDESC typeDesc = elemDesc.tdesc; paramFlags[paramIndex] = elemDesc.desc.paramdesc.wParamFlags; // I think I should never see a retval param here. They have been automatically converted to return types. Debug.Assert((paramFlags[paramIndex] & PARAMFLAG.PARAMFLAG_FRETVAL) == 0); VarEnum variantType = (VarEnum)typeDesc.vt; bool isArray = variantType == VarEnum.VT_SAFEARRAY; bool isPtr = variantType == VarEnum.VT_PTR; bool isOut = (paramFlags[paramIndex] & PARAMFLAG.PARAMFLAG_FOUT) != 0; // VB array params will have isPtr and !isArray, because they are always ByRef (thus ptrs). // In general (always?), out params will be VT_PTR. if (isArray || isPtr) { IntPtr pElementTypeDesc = typeDesc.lpValue; TYPEDESC elementTypeDesc = (TYPEDESC)Marshal.PtrToStructure(pElementTypeDesc, typeof(TYPEDESC)); variantType = (VarEnum)elementTypeDesc.vt; // If the arg was a ptr to an array (e.g., as in VB objects), do it again to get the element type. if (variantType == VarEnum.VT_SAFEARRAY) { isArray = true; pElementTypeDesc = elementTypeDesc.lpValue; elementTypeDesc = (TYPEDESC)Marshal.PtrToStructure(pElementTypeDesc, typeof(TYPEDESC)); variantType = (VarEnum)elementTypeDesc.vt; } } paramTypes[paramIndex] = managedTypeForVariantType(variantType, isArray, isPtr, isOut); } } finally { iTypeInfo.ReleaseFuncDesc(pFuncDesc); } return(true); } catch (Exception) { return(true); } }
public unsafe int RemoteGetFuncDesc(uint index, FUNCDESC** ppFuncDesc, CLEANLOCALSTORAGE* pDummy) { ITypeInfo_vtbl** @this = (ITypeInfo_vtbl**)reference; ITypeInfo_vtbl* vtbl = *@this; if (vtbl == null) throw new InvalidComObjectException(); Delegate genericDelegate = Marshal.GetDelegateForFunctionPointer(vtbl->method_5, typeof(delegate_5)); delegate_5 method = (delegate_5)genericDelegate; return method(@this, index, ppFuncDesc, pDummy); }
public unsafe int RemoteBind(char* szName, uint lHashVal, ushort wFlags, ITypeInfo* ppTInfo, DESCKIND* pDescKind, FUNCDESC** ppFuncDesc, VARDESC** ppVarDesc, ITypeComp* ppTypeComp, CLEANLOCALSTORAGE* pDummy) { ITypeComp_vtbl** @this = (ITypeComp_vtbl**)reference; ITypeComp_vtbl* vtbl = *@this; if (vtbl == null) throw new InvalidComObjectException(); Delegate genericDelegate = Marshal.GetDelegateForFunctionPointer(vtbl->method_3, typeof(delegate_3)); delegate_3 method = (delegate_3)genericDelegate; return method(@this, szName, lHashVal, wFlags, ppTInfo, pDescKind, ppFuncDesc, ppVarDesc, ppTypeComp, pDummy); }