Skip to content

Commit

Permalink
Implement disposable resource pattern in ComReflection (nice catch @b…
Browse files Browse the repository at this point in the history
…clothier). Addresses possible pointer leaks.
  • Loading branch information
comintern committed Jul 16, 2018
1 parent b6b9d74 commit aa7bfdb
Show file tree
Hide file tree
Showing 9 changed files with 153 additions and 130 deletions.
47 changes: 25 additions & 22 deletions Rubberduck.Parsing/ComReflection/ComCoClass.cs
Expand Up @@ -5,6 +5,7 @@
using System.Runtime.InteropServices;
using System.Runtime.InteropServices.ComTypes;
using Rubberduck.Parsing.Symbols;
using Rubberduck.VBEditor.Utility;
using TYPEATTR = System.Runtime.InteropServices.ComTypes.TYPEATTR;
using IMPLTYPEFLAGS = System.Runtime.InteropServices.ComTypes.IMPLTYPEFLAGS;
using TYPEFLAGS = System.Runtime.InteropServices.ComTypes.TYPEFLAGS;
Expand Down Expand Up @@ -63,30 +64,32 @@ private void GetImplementedInterfaces(ITypeInfo info, TYPEATTR typeAttr)
info.GetRefTypeInfo(href, out ITypeInfo implemented);

implemented.GetTypeAttr(out IntPtr attribPtr);
var attribs = (TYPEATTR)Marshal.PtrToStructure(attribPtr, typeof(TYPEATTR));

ComProject.KnownTypes.TryGetValue(attribs.guid, out ComType inherited);
var intface = inherited as ComInterface ?? new ComInterface(implemented, attribs);

ComProject.KnownTypes.TryAdd(attribs.guid, intface);

IMPLTYPEFLAGS flags = 0;
try
{
info.GetImplTypeFlags(implIndex, out flags);
}
catch (COMException) { }

if (flags.HasFlag(IMPLTYPEFLAGS.IMPLTYPEFLAG_FSOURCE))
{
_events.Add(intface);
}
else
using (DisposalActionContainer.Create(attribPtr, info.ReleaseTypeAttr))
{
DefaultInterface = flags.HasFlag(IMPLTYPEFLAGS.IMPLTYPEFLAG_FDEFAULT) ? intface : DefaultInterface;
var attribs = Marshal.PtrToStructure<TYPEATTR>(attribPtr);

ComProject.KnownTypes.TryGetValue(attribs.guid, out ComType inherited);
var intface = inherited as ComInterface ?? new ComInterface(implemented, attribs);

ComProject.KnownTypes.TryAdd(attribs.guid, intface);

IMPLTYPEFLAGS flags = 0;
try
{
info.GetImplTypeFlags(implIndex, out flags);
}
catch (COMException) { }

if (flags.HasFlag(IMPLTYPEFLAGS.IMPLTYPEFLAG_FSOURCE))
{
_events.Add(intface);
}
else
{
DefaultInterface = flags.HasFlag(IMPLTYPEFLAGS.IMPLTYPEFLAG_FDEFAULT) ? intface : DefaultInterface;
}
_interfaces.Add(intface, flags.HasFlag(IMPLTYPEFLAGS.IMPLTYPEFLAG_FRESTRICTED));
}
_interfaces.Add(intface, flags.HasFlag(IMPLTYPEFLAGS.IMPLTYPEFLAG_FRESTRICTED));
info.ReleaseTypeAttr(attribPtr);
}
}
}
Expand Down
9 changes: 6 additions & 3 deletions Rubberduck.Parsing/ComReflection/ComEnumeration.cs
Expand Up @@ -3,6 +3,7 @@
using System.Runtime.InteropServices;
using System.Runtime.InteropServices.ComTypes;
using Rubberduck.Parsing.Symbols;
using Rubberduck.VBEditor.Utility;
using TYPEATTR = System.Runtime.InteropServices.ComTypes.TYPEATTR;
using VARDESC = System.Runtime.InteropServices.ComTypes.VARDESC;

Expand All @@ -26,9 +27,11 @@ private void GetEnumerationMembers(ITypeInfo info, TYPEATTR attrib)
for (var index = 0; index < count; index++)
{
info.GetVarDesc(index, out IntPtr varPtr);
var desc = (VARDESC)Marshal.PtrToStructure(varPtr, typeof(VARDESC));
Members.Add(new ComEnumerationMember(info, desc));
info.ReleaseVarDesc(varPtr);
using (DisposalActionContainer.Create(varPtr, info.ReleaseVarDesc))
{
var desc = Marshal.PtrToStructure<VARDESC>(varPtr);
Members.Add(new ComEnumerationMember(info, desc));
}
}
}
}
Expand Down
18 changes: 10 additions & 8 deletions Rubberduck.Parsing/ComReflection/ComField.cs
Expand Up @@ -5,6 +5,7 @@
using System.Runtime.InteropServices;
using System.Runtime.InteropServices.ComTypes;
using Rubberduck.Parsing.Symbols;
using Rubberduck.VBEditor.Utility;
using TYPEATTR = System.Runtime.InteropServices.ComTypes.TYPEATTR;
using TYPEDESC = System.Runtime.InteropServices.ComTypes.TYPEDESC;
using TYPEKIND = System.Runtime.InteropServices.ComTypes.TYPEKIND;
Expand Down Expand Up @@ -93,23 +94,24 @@ private void GetFieldType(TYPEDESC desc, ITypeInfo info)
try
{
info.GetRefTypeInfo(href, out ITypeInfo refTypeInfo);

refTypeInfo.GetTypeAttr(out IntPtr attribPtr);
var attribs = (TYPEATTR)Marshal.PtrToStructure(attribPtr, typeof(TYPEATTR));
if (attribs.typekind == TYPEKIND.TKIND_ENUM)
using (DisposalActionContainer.Create(attribPtr, refTypeInfo.ReleaseTypeAttr))
{
_enumGuid = attribs.guid;
var attribs = Marshal.PtrToStructure<TYPEATTR>(attribPtr);
if (attribs.typekind == TYPEKIND.TKIND_ENUM)
{
_enumGuid = attribs.guid;
}
IsReferenceType = ReferenceTypeKinds.Contains(attribs.typekind);
_valueType = new ComDocumentation(refTypeInfo, -1).Name;
}
IsReferenceType = ReferenceTypeKinds.Contains(attribs.typekind);
_valueType = new ComDocumentation(refTypeInfo, -1).Name;
refTypeInfo.ReleaseTypeAttr(attribPtr);
}
catch (COMException) { }
break;
case VarEnum.VT_SAFEARRAY:
case VarEnum.VT_CARRAY:
case VarEnum.VT_ARRAY:
tdesc = (TYPEDESC)Marshal.PtrToStructure(desc.lpValue, typeof(TYPEDESC));
tdesc = Marshal.PtrToStructure<TYPEDESC>(desc.lpValue);
GetFieldType(tdesc, info);
IsArray = true;
break;
Expand Down
50 changes: 28 additions & 22 deletions Rubberduck.Parsing/ComReflection/ComInterface.cs
Expand Up @@ -4,6 +4,7 @@
using System.Runtime.InteropServices;
using System.Runtime.InteropServices.ComTypes;
using Rubberduck.Parsing.Symbols;
using Rubberduck.VBEditor.Utility;
using TYPEATTR = System.Runtime.InteropServices.ComTypes.TYPEATTR;
using FUNCDESC = System.Runtime.InteropServices.ComTypes.FUNCDESC;
using CALLCONV = System.Runtime.InteropServices.ComTypes.CALLCONV;
Expand Down Expand Up @@ -52,14 +53,15 @@ private void GetImplementedInterfaces(ITypeInfo info, TYPEATTR typeAttr)
info.GetRefTypeInfo(href, out ITypeInfo implemented);

implemented.GetTypeAttr(out IntPtr attribPtr);
var attribs = (TYPEATTR)Marshal.PtrToStructure(attribPtr, typeof(TYPEATTR));

ComProject.KnownTypes.TryGetValue(attribs.guid, out ComType inherited);
var intface = inherited as ComInterface ?? new ComInterface(implemented, attribs);
_inherited.Add(intface);
ComProject.KnownTypes.TryAdd(attribs.guid, intface);
using (DisposalActionContainer.Create(attribPtr, info.ReleaseTypeAttr))
{
var attribs = Marshal.PtrToStructure<TYPEATTR>(attribPtr);

info.ReleaseTypeAttr(attribPtr);
ComProject.KnownTypes.TryGetValue(attribs.guid, out ComType inherited);
var intface = inherited as ComInterface ?? new ComInterface(implemented, attribs);
_inherited.Add(intface);
ComProject.KnownTypes.TryAdd(attribs.guid, intface);
}
}
}

Expand All @@ -68,18 +70,20 @@ private void GetComMembers(ITypeInfo info, TYPEATTR attrib)
for (var index = 0; index < attrib.cFuncs; index++)
{
info.GetFuncDesc(index, out IntPtr memberPtr);
var member = (FUNCDESC)Marshal.PtrToStructure(memberPtr, typeof(FUNCDESC));
if (member.callconv != CALLCONV.CC_STDCALL)
using (DisposalActionContainer.Create(memberPtr, info.ReleaseFuncDesc))
{
continue;
var member = Marshal.PtrToStructure<FUNCDESC>(memberPtr);
if (member.callconv != CALLCONV.CC_STDCALL)
{
continue;
}
var comMember = new ComMember(info, member);
_members.Add(comMember);
if (comMember.IsDefault)
{
DefaultMember = comMember;
}
}
var comMember = new ComMember(info, member);
_members.Add(comMember);
if (comMember.IsDefault)
{
DefaultMember = comMember;
}
info.ReleaseFuncDesc(memberPtr);
}
}

Expand All @@ -89,12 +93,14 @@ private void GetComProperties(ITypeInfo info, TYPEATTR attrib)
for (var index = 0; index < attrib.cVars; index++)
{
info.GetVarDesc(index, out IntPtr varDescPtr);
var property = (VARDESC)Marshal.PtrToStructure(varDescPtr, typeof(VARDESC));
info.GetNames(property.memid, names, names.Length, out int length);
Debug.Assert(length == 1);
using (DisposalActionContainer.Create(varDescPtr, info.ReleaseVarDesc))
{
var property = Marshal.PtrToStructure<VARDESC>(varDescPtr);
info.GetNames(property.memid, names, names.Length, out int length);
Debug.Assert(length == 1);

_properties.Add(new ComField(info, names[0], property, index, DeclarationType.Property));
info.ReleaseVarDesc(varDescPtr);
_properties.Add(new ComField(info, names[0], property, index, DeclarationType.Property));
}
}
}
}
Expand Down
2 changes: 1 addition & 1 deletion Rubberduck.Parsing/ComReflection/ComMember.cs
Expand Up @@ -98,7 +98,7 @@ private void LoadParameters(FUNCDESC funcDesc, ITypeInfo info)
for (var index = 0; index < count - 1; index++)
{
var paramPtr = new IntPtr(funcDesc.lprgelemdescParam.ToInt64() + Marshal.SizeOf(typeof(ELEMDESC)) * index);
var elemDesc = (ELEMDESC)Marshal.PtrToStructure(paramPtr, typeof(ELEMDESC));
var elemDesc = Marshal.PtrToStructure<ELEMDESC>(paramPtr);
var param = new ComParameter(elemDesc, info, names[index + 1] ?? $"{index}unnamedParameter");
_parameters.Add(param);
}
Expand Down
1 change: 1 addition & 0 deletions Rubberduck.Parsing/ComReflection/ComModule.cs
Expand Up @@ -47,6 +47,7 @@ private void GetComFields(ITypeInfo info, TYPEATTR attrib)
for (var index = 0; index < attrib.cVars; index++)
{
info.GetVarDesc(index, out IntPtr varPtr);

var desc = (VARDESC)Marshal.PtrToStructure(varPtr, typeof(VARDESC));
info.GetNames(desc.memid, names, names.Length, out int length);
Debug.Assert(length == 1);
Expand Down
14 changes: 8 additions & 6 deletions Rubberduck.Parsing/ComReflection/ComParameter.cs
Expand Up @@ -3,6 +3,7 @@
using System.Linq;
using System.Runtime.InteropServices;
using System.Runtime.InteropServices.ComTypes;
using Rubberduck.VBEditor.Utility;
using ELEMDESC = System.Runtime.InteropServices.ComTypes.ELEMDESC;
using PARAMFLAG = System.Runtime.InteropServices.ComTypes.PARAMFLAG;
using TYPEATTR = System.Runtime.InteropServices.ComTypes.TYPEATTR;
Expand Down Expand Up @@ -102,15 +103,16 @@ private void GetParameterType(TYPEDESC desc, ITypeInfo info)
try
{
info.GetRefTypeInfo(href, out ITypeInfo refTypeInfo);

refTypeInfo.GetTypeAttr(out IntPtr attribPtr);
var attribs = (TYPEATTR)Marshal.PtrToStructure(attribPtr, typeof(TYPEATTR));
if (attribs.typekind == TYPEKIND.TKIND_ENUM)
using (DisposalActionContainer.Create(attribPtr, refTypeInfo.ReleaseTypeAttr))
{
_enumGuid = attribs.guid;
var attribs = Marshal.PtrToStructure<TYPEATTR>(attribPtr);
if (attribs.typekind == TYPEKIND.TKIND_ENUM)
{
_enumGuid = attribs.guid;
}
_type = new ComDocumentation(refTypeInfo, -1).Name;
}
_type = new ComDocumentation(refTypeInfo, -1).Name;
refTypeInfo.ReleaseTypeAttr(attribPtr);
}
catch (COMException) { }
break;
Expand Down

0 comments on commit aa7bfdb

Please sign in to comment.