Browse Source
git-svn-id: svn://svn.sharpdevelop.net/sharpdevelop/trunk@5140 1ccf3a8d-04fe-1044-b7c0-cef0b8235c61shortcuts
26 changed files with 226 additions and 506 deletions
@ -0,0 +1,89 @@
@@ -0,0 +1,89 @@
|
||||
// <file>
|
||||
// <copyright see="prj:///doc/copyright.txt"/>
|
||||
// <license see="prj:///doc/license.txt"/>
|
||||
// <owner name="David Srbecký" email="dsrbecky@gmail.com"/>
|
||||
// <version>$Revision$</version>
|
||||
// </file>
|
||||
|
||||
#pragma warning disable 108, 1591
|
||||
|
||||
using System; |
||||
using System.Runtime.CompilerServices; |
||||
using System.Runtime.InteropServices; |
||||
|
||||
namespace Debugger.Interop |
||||
{ |
||||
// These are used in both CorDebug and CorSym
|
||||
|
||||
[StructLayout(LayoutKind.Sequential, Pack=4)] |
||||
public struct _FILETIME |
||||
{ |
||||
public uint dwLowDateTime; |
||||
public uint dwHighDateTime; |
||||
} |
||||
|
||||
[StructLayout(LayoutKind.Sequential, Pack=8)] |
||||
public struct _LARGE_INTEGER |
||||
{ |
||||
public long QuadPart; |
||||
} |
||||
|
||||
[StructLayout(LayoutKind.Sequential, Pack=8)] |
||||
public struct _ULARGE_INTEGER |
||||
{ |
||||
public ulong QuadPart; |
||||
} |
||||
|
||||
[ComImport, Guid("0C733A30-2A1C-11CE-ADE5-00AA0044773D"), InterfaceType((short) 1)] |
||||
public interface ISequentialStream |
||||
{ |
||||
[MethodImpl(MethodImplOptions.InternalCall, MethodCodeType=MethodCodeType.Runtime)] |
||||
void __RemoteRead(out byte pv, [In] uint cb, out uint pcbRead); |
||||
[MethodImpl(MethodImplOptions.InternalCall, MethodCodeType=MethodCodeType.Runtime)] |
||||
void __RemoteWrite([In] ref byte pv, [In] uint cb, out uint pcbWritten); |
||||
} |
||||
|
||||
[ComImport, InterfaceType((short) 1), Guid("0000000C-0000-0000-C000-000000000046")] |
||||
public interface IStream : ISequentialStream |
||||
{ |
||||
[MethodImpl(MethodImplOptions.InternalCall, MethodCodeType=MethodCodeType.Runtime)] |
||||
void __RemoteRead(out byte pv, [In] uint cb, out uint pcbRead); |
||||
[MethodImpl(MethodImplOptions.InternalCall, MethodCodeType=MethodCodeType.Runtime)] |
||||
void __RemoteWrite([In] ref byte pv, [In] uint cb, out uint pcbWritten); |
||||
[MethodImpl(MethodImplOptions.InternalCall, MethodCodeType=MethodCodeType.Runtime)] |
||||
void __RemoteSeek([In] _LARGE_INTEGER dlibMove, [In] uint dwOrigin, out _ULARGE_INTEGER plibNewPosition); |
||||
[MethodImpl(MethodImplOptions.InternalCall, MethodCodeType=MethodCodeType.Runtime)] |
||||
void __SetSize([In] _ULARGE_INTEGER libNewSize); |
||||
[MethodImpl(MethodImplOptions.InternalCall, MethodCodeType=MethodCodeType.Runtime)] |
||||
void __RemoteCopyTo([In, MarshalAs(UnmanagedType.Interface)] IStream pstm, [In] _ULARGE_INTEGER cb, out _ULARGE_INTEGER pcbRead, out _ULARGE_INTEGER pcbWritten); |
||||
[MethodImpl(MethodImplOptions.InternalCall, MethodCodeType=MethodCodeType.Runtime)] |
||||
void __Commit([In] uint grfCommitFlags); |
||||
[MethodImpl(MethodImplOptions.InternalCall, MethodCodeType=MethodCodeType.Runtime)] |
||||
void __Revert(); |
||||
[MethodImpl(MethodImplOptions.InternalCall, MethodCodeType=MethodCodeType.Runtime)] |
||||
void __LockRegion([In] _ULARGE_INTEGER libOffset, [In] _ULARGE_INTEGER cb, [In] uint dwLockType); |
||||
[MethodImpl(MethodImplOptions.InternalCall, MethodCodeType=MethodCodeType.Runtime)] |
||||
void __UnlockRegion([In] _ULARGE_INTEGER libOffset, [In] _ULARGE_INTEGER cb, [In] uint dwLockType); |
||||
[MethodImpl(MethodImplOptions.InternalCall, MethodCodeType=MethodCodeType.Runtime)] |
||||
void __Stat(out tagSTATSTG pstatstg, [In] uint grfStatFlag); |
||||
[MethodImpl(MethodImplOptions.InternalCall, MethodCodeType=MethodCodeType.Runtime)] |
||||
void __Clone([MarshalAs(UnmanagedType.Interface)] out IStream ppstm); |
||||
} |
||||
|
||||
[StructLayout(LayoutKind.Sequential, Pack=8)] |
||||
public struct tagSTATSTG |
||||
{ |
||||
[MarshalAs(UnmanagedType.LPWStr)] |
||||
public string pwcsName; |
||||
public uint type; |
||||
public _ULARGE_INTEGER cbSize; |
||||
public _FILETIME mtime; |
||||
public _FILETIME ctime; |
||||
public _FILETIME atime; |
||||
public uint grfMode; |
||||
public uint grfLocksSupported; |
||||
public Guid clsid; |
||||
public uint grfStateBits; |
||||
public uint reserved; |
||||
} |
||||
} |
||||
@ -1,114 +0,0 @@
@@ -1,114 +0,0 @@
|
||||
// <file>
|
||||
// <copyright see="prj:///doc/copyright.txt"/>
|
||||
// <license see="prj:///doc/license.txt"/>
|
||||
// <owner name="David Srbecký" email="dsrbecky@gmail.com"/>
|
||||
// <version>$Revision$</version>
|
||||
// </file>
|
||||
|
||||
#pragma warning disable 1591
|
||||
|
||||
using Debugger.Internal; |
||||
using System; |
||||
using System.Collections.Generic; |
||||
using System.Runtime.InteropServices; |
||||
using Debugger.Interop; |
||||
|
||||
namespace Debugger.Interop |
||||
{ |
||||
class TrackedObjectMetaData |
||||
{ |
||||
public Type ObjectType; |
||||
public int RefCount; |
||||
|
||||
public TrackedObjectMetaData(Type objectType, int refCount) |
||||
{ |
||||
this.ObjectType = objectType; |
||||
this.RefCount = refCount; |
||||
} |
||||
} |
||||
|
||||
public static class ResourceManager |
||||
{ |
||||
static MTA2STA mta2sta = new MTA2STA(); |
||||
static bool trace = false; |
||||
static Dictionary<object, TrackedObjectMetaData> trackedCOMObjects = new Dictionary<object, TrackedObjectMetaData>(); |
||||
|
||||
public static bool TraceMessagesEnabled { |
||||
get { |
||||
return trace; |
||||
} |
||||
set { |
||||
trace = value; |
||||
} |
||||
} |
||||
|
||||
public static void TrackCOMObject(object comObject, Type type) |
||||
{ |
||||
if (comObject == null || !Marshal.IsComObject(comObject)) { |
||||
if (trace) Trace("Will not be tracked: {0}", type.Name); |
||||
} else { |
||||
TrackedObjectMetaData metaData; |
||||
if (trackedCOMObjects.TryGetValue(comObject, out metaData)) { |
||||
metaData.RefCount += 1; |
||||
} else { |
||||
metaData = new TrackedObjectMetaData(type,1); |
||||
trackedCOMObjects.Add(comObject, metaData); |
||||
} |
||||
if (trace) Trace("AddRef {0,2}: {1}", metaData.RefCount, type.Name); |
||||
} |
||||
} |
||||
|
||||
public static void ReleaseCOMObject(object comObject, Type type) |
||||
{ |
||||
// Ensure that the release is done synchronosly
|
||||
try { |
||||
mta2sta.AsyncCall(delegate { |
||||
ReleaseCOMObjectInternal(comObject, type); |
||||
}); |
||||
} catch (InvalidOperationException) { |
||||
// This might happen when the application is shuting down
|
||||
} |
||||
} |
||||
|
||||
static void ReleaseCOMObjectInternal(object comObject, Type type) |
||||
{ |
||||
TrackedObjectMetaData metaData; |
||||
if (comObject != null && trackedCOMObjects.TryGetValue(comObject, out metaData)) { |
||||
metaData.RefCount -= 1; |
||||
if (metaData.RefCount == 0) { |
||||
Marshal.FinalReleaseComObject(comObject); |
||||
trackedCOMObjects.Remove(comObject); |
||||
} |
||||
if (trace) Trace("Release {0,2}: {1}", metaData.RefCount, type.Name); |
||||
} else { |
||||
if (trace) Trace("Was not tracked: {0}", type.Name); |
||||
} |
||||
} |
||||
|
||||
public static void ReleaseAllTrackedCOMObjects() |
||||
{ |
||||
if (trace) Trace("Releasing {0} tracked COM objects... ", trackedCOMObjects.Count); |
||||
while(trackedCOMObjects.Count > 0) { |
||||
foreach (KeyValuePair<object, TrackedObjectMetaData> pair in trackedCOMObjects) { |
||||
Marshal.FinalReleaseComObject(pair.Key); |
||||
if (trace) Trace(" * Releasing {0} ({1} references)", pair.Value.ObjectType.Name, pair.Value.RefCount); |
||||
trackedCOMObjects.Remove(pair.Key); |
||||
break; |
||||
} |
||||
} |
||||
if (trace) Trace(" * Done"); |
||||
} |
||||
|
||||
public static event EventHandler<MessageEventArgs> TraceMessage; |
||||
|
||||
static void Trace(string msg, params object[] pars) |
||||
{ |
||||
if (TraceMessage != null && trace) { |
||||
string message = String.Format("COM({0,-3}): {1}", trackedCOMObjects.Count, String.Format(msg, pars)); |
||||
TraceMessage(null, new MessageEventArgs(null, message)); |
||||
} |
||||
} |
||||
} |
||||
} |
||||
|
||||
#pragma warning restore 1591
|
||||
@ -0,0 +1,61 @@
@@ -0,0 +1,61 @@
|
||||
// <file>
|
||||
// <copyright see="prj:///doc/copyright.txt"/>
|
||||
// <license see="prj:///doc/license.txt"/>
|
||||
// <owner name="David Srbecký" email="dsrbecky@gmail.com"/>
|
||||
// <version>$Revision$</version>
|
||||
// </file>
|
||||
|
||||
#pragma warning disable 1591
|
||||
|
||||
using System; |
||||
using System.Collections.Generic; |
||||
using System.Runtime.InteropServices; |
||||
|
||||
namespace Debugger.Interop |
||||
{ |
||||
public static class TrackedComObjects |
||||
{ |
||||
static List<WeakReference> objects = new List<WeakReference>(); |
||||
|
||||
public static void ProcessOutParameter(object parameter) |
||||
{ |
||||
if (parameter != null) { |
||||
if (Marshal.IsComObject(parameter)) { |
||||
Track(parameter); |
||||
} else if (parameter is Array) { |
||||
foreach(object elem in (Array)parameter) { |
||||
ProcessOutParameter(elem); |
||||
} |
||||
} |
||||
} |
||||
} |
||||
|
||||
public static void Track(object obj) |
||||
{ |
||||
if (Marshal.IsComObject(obj)) { |
||||
lock(objects) { |
||||
objects.Add(new WeakReference(obj)); |
||||
} |
||||
} |
||||
} |
||||
|
||||
public static int ReleaseAll() |
||||
{ |
||||
lock(objects) { |
||||
int count = 0; |
||||
foreach(WeakReference weakRef in objects) { |
||||
object obj = weakRef.Target; |
||||
if (obj != null) { |
||||
Marshal.FinalReleaseComObject(obj); |
||||
count++; |
||||
} |
||||
} |
||||
objects.Clear(); |
||||
objects.TrimExcess(); |
||||
return count; |
||||
} |
||||
} |
||||
} |
||||
} |
||||
|
||||
#pragma warning restore 1591
|
||||
Loading…
Reference in new issue