public override int GetDocumentation(int memid, IntPtr strName, IntPtr strDocString, IntPtr dwHelpContext, IntPtr strHelpFile) { if (memid == (int)KnownDispatchMemberIDs.MEMBERID_NIL) { if (strName != IntPtr.Zero) { RdMarshal.WriteIntPtr(strName, Marshal.StringToBSTR("_ArtificialContainer")); } if (strDocString != IntPtr.Zero) { RdMarshal.WriteIntPtr(strDocString, IntPtr.Zero); } if (dwHelpContext != IntPtr.Zero) { RdMarshal.WriteInt32(dwHelpContext, 0); } if (strHelpFile != IntPtr.Zero) { RdMarshal.WriteIntPtr(strHelpFile, IntPtr.Zero); } return((int)KnownComHResults.S_OK); } return((int)KnownComHResults.TYPE_E_ELEMENTNOTFOUND); }
public override void ReleaseTLibAttr(IntPtr pTLibAttr) { if (pTLibAttr != IntPtr.Zero) { RdMarshal.FreeHGlobal(pTLibAttr); } }
public override int GetTypeAttr(IntPtr ppTypeAttr) { var hr = _target_ITypeInfo.GetTypeAttr(ppTypeAttr); if (ComHelper.HRESULT_FAILED(hr)) { return(HandleBadHRESULT(hr)); } var pTypeAttr = StructHelper.ReadStructureUnsafe <IntPtr>(ppTypeAttr); var typeAttr = StructHelper.ReadStructureUnsafe <ComTypes.TYPEATTR>(pTypeAttr); typeAttr.typekind = PatchTypeKind((TYPEKIND_VBE)typeAttr.typekind); // A proper type library would not have any variables defined in the modules. // However, a VBA module can have those and that can trip up CLR's parser. To // work around this, we lie to any ComTypes.ITypeInfo consumer that there's no // variables. If we need for VBA-specific work, we need to consult // ITypeInfoWrapper.Vars instead. if (typeAttr.typekind == ComTypes.TYPEKIND.TKIND_MODULE && typeAttr.cVars > 0) { typeAttr.cVars = (short)Consts.Count; } RdMarshal.StructureToPtr <ComTypes.TYPEATTR>(typeAttr, pTypeAttr, true); return(hr); }
public override int GetLibAttr(IntPtr ppTLibAttr) { var output = RdMarshal.AllocHGlobal(Marshal.SizeOf(typeof(ComTypes.TYPELIBATTR))); RdMarshal.StructureToPtr(_libAttribs, output, false); RdMarshal.WriteIntPtr(ppTLibAttr, output); return((int)KnownComHResults.S_OK); }
/// <summary> /// Gets the control <see cref="ComTypes.ITypeInfo"/> by looking for the /// corresponding getter on the form interface and returning its retval type /// </summary> /// <param name="controlName">the name of the control</param> /// <returns> /// <see cref="ITypeInfoWrapper"/> representing the type of control, /// typically the coclass, but this is host dependent /// </returns> public static ITypeInfoWrapper GetControlTypeFromInterface(ITypeInfoWrapper rootInterface, string controlName) { // TODO should encapsulate handling of raw datatypes foreach (var func in rootInterface.Funcs) { using (func) { // Controls are exposed as getters on the interface. // can either be ControlType* get_ControlName() // or HRESULT get_ControlName(ControlType** Out) if ((func.Name == controlName) && (func.ProcKind == PROCKIND.PROCKIND_GET) && (func.ParamCount == 0) && (func.FuncDesc.elemdescFunc.tdesc.vt == (short)VarEnum.VT_PTR)) { var retValElement = StructHelper.ReadStructureUnsafe <ComTypes.ELEMDESC>(func.FuncDesc.elemdescFunc.tdesc.lpValue); if (retValElement.tdesc.vt == (short)VarEnum.VT_USERDEFINED) { var hr = rootInterface.GetSafeRefTypeInfo((int)retValElement.tdesc.lpValue, out var retVal); if (ComHelper.HRESULT_FAILED(hr)) { throw RdMarshal.GetExceptionForHR(hr); } return(retVal); } } else if ((func.Name == controlName) && (func.ProcKind == PROCKIND.PROCKIND_GET) && (func.ParamCount == 1) && (func.FuncDesc.elemdescFunc.tdesc.vt == (short)VarEnum.VT_HRESULT)) { // Get details of the first argument var retValElementOuterPtr = StructHelper.ReadStructureUnsafe <ComTypes.ELEMDESC>(func.FuncDesc.lprgelemdescParam); if (retValElementOuterPtr.tdesc.vt == (short)VarEnum.VT_PTR) { var retValElementInnerPtr = StructHelper.ReadStructureUnsafe <ComTypes.ELEMDESC>(retValElementOuterPtr.tdesc.lpValue); if (retValElementInnerPtr.tdesc.vt == (short)VarEnum.VT_PTR) { var retValElement = StructHelper.ReadStructureUnsafe <ComTypes.ELEMDESC>(retValElementInnerPtr.tdesc.lpValue); if (retValElement.tdesc.vt == (short)VarEnum.VT_USERDEFINED) { var hr = rootInterface.GetSafeRefTypeInfo((int)retValElement.tdesc.lpValue, out var retVal); if (ComHelper.HRESULT_FAILED(hr)) { throw RdMarshal.GetExceptionForHR(hr); } return(retVal); } } } } } } throw new ArgumentException($"TypeInfoWrapper::GetControlType failed. '{controlName}' control not found."); }
public override int GetRefTypeInfo(int hRef, IntPtr ppTI) { var hr = GetSafeRefTypeInfo(hRef, out var ti); if (ComHelper.HRESULT_FAILED(hr)) { return(HandleBadHRESULT(hr)); } RdMarshal.WriteIntPtr(ppTI, ti.GetCOMReferencePtr()); return(hr); }
public override int GetTypeInfo(int index, IntPtr ppTI) { if (index >= _containedTypeInfos.Count) { return((int)KnownComHResults.TYPE_E_ELEMENTNOTFOUND); } var ti = _containedTypeInfos[index]; RdMarshal.WriteIntPtr(ppTI, ti.GetCOMReferencePtr()); return((int)KnownComHResults.S_OK); }
public override int GetDocumentation(int memid, IntPtr strName, IntPtr strDocString, IntPtr dwHelpContext, IntPtr strHelpFile) { if (IsDispatchMemberIDInOurConstantsRange(memid)) { // this is very likely one of our simulated names from GetVarDesc() var fieldId = memid & _ourConstantsDispatchMemberIDIndexBitmask; if (strName != IntPtr.Zero) { RdMarshal.WriteIntPtr(strName, Marshal.StringToBSTR("_constantFieldId" + fieldId)); } if (strDocString != IntPtr.Zero) { RdMarshal.WriteIntPtr(strDocString, IntPtr.Zero); } if (dwHelpContext != IntPtr.Zero) { RdMarshal.WriteInt32(dwHelpContext, 0); } if (strHelpFile != IntPtr.Zero) { RdMarshal.WriteIntPtr(strHelpFile, IntPtr.Zero); } return((int)KnownComHResults.S_OK); } if (memid == (int)KnownDispatchMemberIDs.MEMBERID_NIL) { // return the cached information here, to workaround the VBE bug for unnamed UserForm base classes causing an access violation if (strName != IntPtr.Zero) { RdMarshal.WriteIntPtr(strName, RdMarshal.StringToBSTR(Name)); } if (strDocString != IntPtr.Zero) { RdMarshal.WriteIntPtr(strDocString, RdMarshal.StringToBSTR(DocString)); } if (dwHelpContext != IntPtr.Zero) { RdMarshal.WriteInt32(dwHelpContext, HelpContext); } if (strHelpFile != IntPtr.Zero) { RdMarshal.WriteIntPtr(strHelpFile, RdMarshal.StringToBSTR(HelpFile)); } return((int)KnownComHResults.S_OK); } else { var hr = _target_ITypeInfo.GetDocumentation(memid, strName, strDocString, dwHelpContext, strHelpFile); return(ComHelper.HRESULT_FAILED(hr) ? HandleBadHRESULT(hr) : hr); } }
public override int GetTypeInfo(int index, IntPtr ppTI) { // We have to wrap the ITypeInfo returned by GetTypeInfo var hr = GetSafeTypeInfoByIndex(index, out var ti); if (ComHelper.HRESULT_FAILED(hr)) { return(HandleBadHRESULT(hr)); } RdMarshal.WriteIntPtr(ppTI, ti.GetCOMReferencePtr()); return(hr); }
public override int GetTypeInfoOfGuid(ref Guid guid, IntPtr ppTInfo) { var inGuid = guid; var ti = _containedTypeInfos.Find(x => x.GUID == inGuid); if (ti == null) { return((int)KnownComHResults.TYPE_E_ELEMENTNOTFOUND); } RdMarshal.WriteIntPtr(ppTInfo, ti.GetCOMReferencePtr()); return((int)KnownComHResults.S_OK); }
public override int GetTypeInfoType(int index, IntPtr pTKind) { if (index >= _containedTypeInfos.Count) { return((int)KnownComHResults.TYPE_E_ELEMENTNOTFOUND); } var ti = _containedTypeInfos[index]; var typeKind = TypeInfoWrapper.PatchTypeKind(ti.TypeKind); RdMarshal.WriteInt32(pTKind, (int)typeKind); return((int)KnownComHResults.S_OK); }
public override int GetTypeInfoType(int index, IntPtr pTKind) { var hr = _target_ITypeLib.GetTypeInfoType(index, pTKind); if (ComHelper.HRESULT_FAILED(hr)) { return(HandleBadHRESULT(hr)); } var tKind = RdMarshal.ReadInt32(pTKind); tKind = (int)TypeInfoWrapper.PatchTypeKind((TYPEKIND_VBE)tKind); RdMarshal.WriteInt32(pTKind, tKind); return(hr); }
public override int GetContainingTypeLib(IntPtr ppTLB, IntPtr pIndex) { // even though pIndex is described as a non-optional OUT argument, mscorlib sometimes calls this with a nullptr from the C++ side. if (pIndex == IntPtr.Zero) { RdMarshal.WriteIntPtr(ppTLB, IntPtr.Zero); return((int)KnownComHResults.E_INVALIDARG); } RdMarshal.WriteIntPtr(ppTLB, RdMarshal.GetComInterfaceForObject(_container, typeof(ITypeLibInternal))); if (pIndex != IntPtr.Zero) { RdMarshal.WriteInt32(pIndex, ContainerIndex); } return((int)KnownComHResults.S_OK); }
public override int GetVarDesc(int index, IntPtr ppVarDesc) { var safeIndex = _consts != null && _consts.Count > 0 ? _consts.MappedIndex(index) : index; var hr = _target_ITypeInfo.GetVarDesc(safeIndex, ppVarDesc); if (ComHelper.HRESULT_FAILED(hr)) { return(HandleBadHRESULT(hr)); } var pVarDesc = StructHelper.ReadStructureUnsafe <IntPtr>(ppVarDesc); var varDesc = StructHelper.ReadStructureUnsafe <ComTypes.VARDESC>(pVarDesc); if (varDesc.memid == (int)KnownDispatchMemberIDs.MEMBERID_NIL) { // constants are not reported correctly in VBA type infos. They all have MEMBERID_NIL set. // we will provide fake DispIds and names to satisfy parsers. Shit but works for now. varDesc.memid = (int)(_ourConstantsDispatchMemberIDRangeStart + safeIndex); RdMarshal.StructureToPtr(varDesc, pVarDesc, true); } else { // Unlike GetFuncDesc, we can't get the wVarFlags for fields from the alternative VBA ITypeInfo // because GetVarDesc() hard crashes on the alternative typeinfo /* * if (target_ITypeInfoAlternate != null) * { * using (var varDescPtr2 = AddressableVariables.CreatePtrTo<ComTypes.VARDESC>()) * { * var hr2 = target_ITypeInfoAlternate.GetVarDesc(index, varDescPtr2.Address); * var varDesc2 = varDescPtr2.Value.Value; // dereference the ptr, then the content * VarDesc.wVarFlags = varDesc2.wVarFlags; * RdMarshal.StructureToPtr(VarDesc, pVarDesc, false); * } * } */ } return(hr); }
public override int GetFuncDesc(int index, IntPtr ppFuncDesc) { var hr = _target_ITypeInfo.GetFuncDesc(index, ppFuncDesc); if (ComHelper.HRESULT_FAILED(hr)) { return(HandleBadHRESULT(hr)); } if (_target_ITypeInfoAlternate != null) { var pFuncDesc = StructHelper.ReadStructureUnsafe <IntPtr>(ppFuncDesc); var funcDesc = StructHelper.ReadStructureUnsafe <ComTypes.FUNCDESC>(pFuncDesc); // Populate wFuncFlags from the alternative typeinfo provided by VBA // The alternative typeinfo is not as useful as the main typeinfo for most things, but does expose wFuncFlags // The list of functions appears to be in the same order as the main typeinfo. using (var funcDescAlternatePtr = AddressableVariables.CreatePtrTo <ComTypes.FUNCDESC>()) { var hr2 = _target_ITypeInfoAlternate.GetFuncDesc(index, funcDescAlternatePtr.Address); if (!ComHelper.HRESULT_FAILED(hr2)) { var funcDescAlternate = funcDescAlternatePtr.Value.Value; // dereference the ptr, then the content //sanity check if (funcDescAlternate.memid == funcDesc.memid) { funcDesc.wFuncFlags = funcDescAlternate.wFuncFlags; } else { Debug.Assert(false, $"The sanity check failed; {nameof(funcDesc.memid)}: {funcDesc.memid} and {nameof(funcDescAlternate.memid)}: {funcDescAlternate.memid}"); } _target_ITypeInfoAlternate.ReleaseFuncDesc(funcDescAlternatePtr.Value.Address); RdMarshal.StructureToPtr(funcDesc, pFuncDesc, true); } } } return(hr); }
public override int GetTypeInfoOfGuid(ref Guid guid, IntPtr ppTInfo) { var hr = _target_ITypeLib.GetTypeInfoOfGuid(guid, ppTInfo); if (ComHelper.HRESULT_FAILED(hr)) { return(HandleBadHRESULT(hr)); } var pTInfo = RdMarshal.ReadIntPtr(ppTInfo); using (var outVal = TypeApiFactory.GetTypeInfoWrapper(pTInfo)) // takes ownership of the COM reference [pTInfo] { RdMarshal.WriteIntPtr(ppTInfo, outVal.GetCOMReferencePtr()); _cachedTypeInfos = _cachedTypeInfos ?? new DisposableList <ITypeInfoWrapper>(); _cachedTypeInfos.Add(outVal); } return(hr); }
/// <summary> /// Executes a procedure inside a standard module in a VBA project /// </summary> /// <param name="name">the name of the procedure to invoke</param> /// <param name="args">arguments to pass to the procedure</param> /// <remarks>the returned object can be a COM object, and the callee is responsible for releasing it appropriately</remarks> /// <returns>an object representing the return value from the procedure, or null if none.</returns> public object StdModExecute(string name, object[] args = null) { // We search for the dispId using the real type info rather than using staticModule.GetIdsOfNames, // as we can then also include PRIVATE scoped procedures. var func = _parent.Funcs.Find(name, PROCKIND.PROCKIND_PROC); if (func == null) { throw new ArgumentException($"StdModExecute failed. Couldn't find procedure named '{name}'"); } var staticModule = GetStdModAccessor(); try { return(IDispatchHelper.Invoke(staticModule, func.FuncDesc.memid, IDispatchHelper.InvokeKind.DISPATCH_METHOD, args)); } finally { RdMarshal.ReleaseComObject(staticModule); } }
public override int GetNames(int memid, IntPtr rgBstrNames, int cMaxNames, IntPtr pcNames) { if (IsDispatchMemberIDInOurConstantsRange(memid)) { // this is most likely one of our simulated names from GetVarDesc() var fieldId = memid & _ourConstantsDispatchMemberIDIndexBitmask; if ((rgBstrNames != IntPtr.Zero) && (cMaxNames >= 1)) { // output 1 string to the array RdMarshal.WriteIntPtr(rgBstrNames, RdMarshal.StringToBSTR("_constantFieldId" + fieldId)); if (pcNames != IntPtr.Zero) { RdMarshal.WriteInt32(pcNames, 1); } return((int)KnownComHResults.S_OK); } } var hr = _target_ITypeInfo.GetNames(memid, rgBstrNames, cMaxNames, pcNames); return(ComHelper.HRESULT_FAILED(hr) ? HandleBadHRESULT(hr) : hr); }
public IntPtr GetCOMReferencePtr() => RdMarshal.GetComInterfaceForObject(this, typeof(ITypeLibInternal));