Skip to content

Commit 51c2a79

Browse files
corrected and clarified refcounts in TypeLibWrapper and TypeInfoWrapper constructors
1 parent 06ee366 commit 51c2a79

File tree

2 files changed

+15
-15
lines changed

2 files changed

+15
-15
lines changed

Rubberduck.VBEEditor/ComManagement/TypeLibs/TypeInfos.cs

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -484,7 +484,7 @@ private void InitCommon()
484484
// so we cast to our ITypeInfo_Ptrs interface in order to work with the raw IntPtrs
485485
IntPtr typeLibPtr = IntPtr.Zero;
486486
((ITypeInfo_Ptrs)target_ITypeInfo).GetContainingTypeLib(out typeLibPtr, out _containerTypeLibIndex);
487-
_containerTypeLib = new TypeLibWrapper(typeLibPtr); // takes ownership of the COM reference
487+
_containerTypeLib = new TypeLibWrapper(typeLibPtr, true);
488488
}
489489
catch (Exception e)
490490
{
@@ -514,6 +514,10 @@ public TypeInfoWrapper(ComTypes.ITypeInfo rawTypeInfo)
514514
public TypeInfoWrapper(IntPtr rawObjectPtr, int? parentUserFormUniqueId = null)
515515
{
516516
_rawObjectPtr = rawObjectPtr;
517+
if (_rawObjectPtr == IntPtr.Zero)
518+
{
519+
throw new ArgumentException("Unepectedly received a null pointer.");
520+
}
517521

518522
// We have to restrict interface requests to VBE hosted ITypeInfos due to a bug in their implementation.
519523
// See TypeInfoWrapper class XML doc for details.
@@ -546,6 +550,8 @@ public void Dispose()
546550
_ITypeInfo_Aggregator?.Dispose();
547551
_IVBEComponent_Aggregator?.Dispose();
548552
_IVBETypeInfo_Aggregator?.Dispose();
553+
554+
Marshal.Release(_rawObjectPtr);
549555
}
550556

551557
private TypeLibTextFields? _cachedTextFields;

Rubberduck.VBEEditor/ComManagement/TypeLibs/TypeLibs.cs

Lines changed: 8 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -147,9 +147,9 @@ public TypeLibWrapper GetVBEReferenceTypeLibByIndex(int index)
147147
IntPtr referenceTypeLibPtr = target_IVBEProject.GetReferenceTypeLib(index);
148148
if (referenceTypeLibPtr == IntPtr.Zero)
149149
{
150-
throw new ArgumentException("$Reference TypeLib not available - probably a missing reference.");
150+
throw new ArgumentException("Reference TypeLib not available - probably a missing reference.");
151151
}
152-
return new TypeLibWrapper(referenceTypeLibPtr);
152+
return new TypeLibWrapper(referenceTypeLibPtr, isRefCountedInput: true);
153153
}
154154

155155
public TypeInfoReference GetVBEReferenceByGuid(Guid referenceGuid)
@@ -202,7 +202,7 @@ public static TypeLibWrapper FromVBProject(IVBProject vbProject)
202202
{
203203
// Now we've got the references object, we can read the internal object structure to grab the ITypeLib
204204
var internalReferencesObj = StructHelper.ReadComObjectStructure<VBEReferencesObj>(references.Target);
205-
return new TypeLibWrapper(internalReferencesObj.TypeLib);
205+
return new TypeLibWrapper(internalReferencesObj.TypeLib, isRefCountedInput: false);
206206
}
207207
}
208208

@@ -217,14 +217,14 @@ private void InitCommon()
217217
/// Constructor
218218
/// </summary>
219219
/// <param name="rawObjectPtr">The raw unamanaged ITypeLib pointer</param>
220-
public TypeLibWrapper(IntPtr rawObjectPtr)
220+
public TypeLibWrapper(IntPtr rawObjectPtr, bool isRefCountedInput)
221221
{
222222
if (!UnmanagedMemHelper.ValidateComObject(rawObjectPtr))
223223
{
224224
throw new ArgumentException("Expected COM object, but validation failed.");
225225
};
226226
target_ITypeLib = (ComTypes.ITypeLib)Marshal.GetObjectForIUnknown(rawObjectPtr);
227-
Marshal.Release(rawObjectPtr); // target_ITypeLib holds a reference to this now
227+
if (isRefCountedInput) Marshal.Release(rawObjectPtr);
228228
InitCommon();
229229
}
230230

@@ -297,7 +297,7 @@ public bool CompileProject()
297297
#if DEBUG
298298
if (e.HResult != (int)KnownComHResults.E_VBA_COMPILEERROR)
299299
{
300-
// this is more for debug purposes, as we can probably just return false in future.
300+
// this is for debug purposes, to see if the compiler ever returns other errors on failure
301301
throw new ArgumentException("Unrecognised VBE compiler error: \n" + e.ToString());
302302
}
303303
#endif
@@ -466,14 +466,8 @@ public void Dispose()
466466
IEnumerator IEnumerable.GetEnumerator() => this;
467467
public IEnumerator<TypeLibWrapper> GetEnumerator() => this;
468468

469-
public IntPtr GetCurrentReference()
470-
{
471-
Marshal.AddRef(_currentTypeLibPtr);
472-
return _currentTypeLibPtr;
473-
}
474-
475-
TypeLibWrapper IEnumerator<TypeLibWrapper>.Current => new TypeLibWrapper(GetCurrentReference());
476-
object IEnumerator.Current => new TypeLibWrapper(GetCurrentReference());
469+
TypeLibWrapper IEnumerator<TypeLibWrapper>.Current => new TypeLibWrapper(_currentTypeLibPtr, isRefCountedInput: false);
470+
object IEnumerator.Current => new TypeLibWrapper(_currentTypeLibPtr, isRefCountedInput: false);
477471

478472
public void Reset() // walk back to the first project in the chain
479473
{

0 commit comments

Comments
 (0)