Code:
/ Net / Net / 3.5.50727.3053 / DEVDIV / depot / DevDiv / releases / whidbey / netfxsp / ndp / clr / src / BCL / System / Runtime / InteropServices / GcHandle.cs / 1 / GcHandle.cs
// ==++==
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
// ==--==
namespace System.Runtime.InteropServices
{
using System;
using System.Security.Permissions;
using System.Runtime.CompilerServices;
using System.Threading;
// These are the types of handles used by the EE. IMPORTANT: These must
// match the definitions in ObjectHandle.h in the EE.
[Serializable]
[System.Runtime.InteropServices.ComVisible(true)]
public enum GCHandleType
{
Weak = 0,
WeakTrackResurrection = 1,
Normal = 2,
Pinned = 3
}
// This class allows you to create an opaque, GC handle to any
// COM+ object. A GC handle is used when an object reference must be
// reachable from unmanaged memory. There are 3 kinds of roots:
// Normal - keeps the object from being collected.
// Weak - allows object to be collected and handle contents will be zeroed.
// Weak references are zeroed before the finalizer runs, so if the
// object is resurrected in the finalizer the weak reference is
// still zeroed.
// WeakTrackResurrection - Same as weak, but stays until after object is
// really gone.
// Pinned - same as normal, but allows the address of the actual object
// to be taken.
//
[StructLayout(LayoutKind.Sequential)]
[System.Runtime.InteropServices.ComVisible(true)]
public struct GCHandle
{
internal static readonly IntPtr InvalidCookie = new IntPtr(unchecked((int)0xFFFFFFFF));
#if MDA_SUPPORTED
static GCHandle()
{
s_probeIsActive = Mda.IsInvalidGCHandleCookieProbeEnabled();
if (s_probeIsActive)
s_cookieTable = new GCHandleCookieTable();
}
#endif
// Allocate a handle storing the object and the type.
internal GCHandle(Object value, GCHandleType type)
{
m_handle = InternalAlloc(value, type);
// Record if the handle is pinned.
if (type == GCHandleType.Pinned)
SetIsPinned();
}
// Used in the conversion functions below.
internal GCHandle(IntPtr handle)
{
InternalCheckDomain(handle);
m_handle = handle;
}
// Creates a new GC handle for an object.
//
// value - The object that the GC handle is created for.
// type - The type of GC handle to create.
//
// returns a new GC handle that protects the object.
[SecurityPermissionAttribute(SecurityAction.LinkDemand, Flags=SecurityPermissionFlag.UnmanagedCode)]
public static GCHandle Alloc(Object value)
{
return new GCHandle(value, GCHandleType.Normal);
}
[SecurityPermissionAttribute(SecurityAction.LinkDemand, Flags=SecurityPermissionFlag.UnmanagedCode)]
public static GCHandle Alloc(Object value, GCHandleType type)
{
return new GCHandle(value, type);
}
// Frees a GC handle.
[SecurityPermissionAttribute(SecurityAction.LinkDemand, Flags=SecurityPermissionFlag.UnmanagedCode)]
public void Free()
{
// Copy the handle instance member to a local variable. This is required to prevent
// race conditions releasing the handle.
IntPtr handle = m_handle;
// Free the handle if it hasn't already been freed.
if (handle != IntPtr.Zero && Interlocked.CompareExchange(ref m_handle, IntPtr.Zero, handle) == handle)
{
#if WIN32
InternalFree((IntPtr)(((int)handle) & ~1));
#else
InternalFree((IntPtr)(((long)handle) & ~1L));
#endif
#if MDA_SUPPORTED
// If this handle was passed out to unmanaged code, we need to remove it
// from the cookie table.
if (s_probeIsActive)
s_cookieTable.RemoveHandleIfPresent(handle);
#endif
}
else
{
throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_HandleIsNotInitialized"));
}
}
// Target property - allows getting / updating of the handle's referent.
public Object Target
{
[SecurityPermissionAttribute(SecurityAction.LinkDemand, Flags=SecurityPermissionFlag.UnmanagedCode)]
get
{
// Check if the handle was never initialized or was freed.
if (m_handle == IntPtr.Zero)
throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_HandleIsNotInitialized"));
return InternalGet(GetHandleValue());
}
[SecurityPermissionAttribute(SecurityAction.LinkDemand, Flags=SecurityPermissionFlag.UnmanagedCode)]
set
{
// Check if the handle was never initialized or was freed.
if (m_handle == IntPtr.Zero)
throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_HandleIsNotInitialized"));
InternalSet(GetHandleValue(), value, IsPinned());
}
}
// Retrieve the address of an object in a Pinned handle. This throws
// an exception if the handle is any type other than Pinned.
[SecurityPermissionAttribute(SecurityAction.LinkDemand, Flags=SecurityPermissionFlag.UnmanagedCode)]
public IntPtr AddrOfPinnedObject()
{
// Check if the handle was not a pinned handle.
if (!IsPinned())
{
// Check if the handle was never initialized for was freed.
if (m_handle == IntPtr.Zero)
throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_HandleIsNotInitialized"));
// You can only get the address of pinned handles.
throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_HandleIsNotPinned"));
}
// Get the address.
return InternalAddrOfPinnedObject(GetHandleValue());
}
// Determine whether this handle has been allocated or not.
public bool IsAllocated
{
get
{
return m_handle != IntPtr.Zero;
}
}
// Used to create a GCHandle from an int. This is intended to
// be used with the reverse conversion.
[SecurityPermissionAttribute(SecurityAction.LinkDemand, Flags=SecurityPermissionFlag.UnmanagedCode)]
public static explicit operator GCHandle(IntPtr value)
{
return FromIntPtr(value);
}
[SecurityPermissionAttribute(SecurityAction.LinkDemand, Flags=SecurityPermissionFlag.UnmanagedCode)]
public static GCHandle FromIntPtr(IntPtr value)
{
if (value == IntPtr.Zero)
throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_HandleIsNotInitialized"));
IntPtr handle = value;
#if MDA_SUPPORTED
if (s_probeIsActive)
{
// Make sure this cookie matches up with a GCHandle we've passed out a cookie for.
handle = s_cookieTable.GetHandle(value);
if (IntPtr.Zero == handle)
{
// Fire an MDA if we were unable to retrieve the GCHandle.
Mda.FireInvalidGCHandleCookieProbe(value);
return new GCHandle(IntPtr.Zero);
}
}
#endif
return new GCHandle(handle);
}
// Used to get the internal integer representation of the handle out.
public static explicit operator IntPtr(GCHandle value)
{
return ToIntPtr(value);
}
public static IntPtr ToIntPtr(GCHandle value)
{
#if MDA_SUPPORTED
if (s_probeIsActive)
{
// Remember that we passed this GCHandle out by storing the cookie we returned so we
// can later validate.
return s_cookieTable.FindOrAddHandle(value.m_handle);
}
#endif
return value.m_handle;
}
public override int GetHashCode()
{
return (int)m_handle;
}
public override bool Equals(Object o)
{
GCHandle hnd;
// Check that o is a GCHandle first
if(o == null || !(o is GCHandle))
return false;
else
hnd = (GCHandle) o;
return m_handle == hnd.m_handle;
}
public static bool operator ==(GCHandle a, GCHandle b)
{
return a.m_handle == b.m_handle;
}
public static bool operator !=(GCHandle a, GCHandle b)
{
return a.m_handle != b.m_handle;
}
internal IntPtr GetHandleValue()
{
#if WIN32
return new IntPtr(((int)m_handle) & ~1);
#else
return new IntPtr(((long)m_handle) & ~1L);
#endif
}
internal bool IsPinned()
{
#if WIN32
return (((int)m_handle) & 1) != 0;
#else
return (((long)m_handle) & 1) != 0;
#endif
}
internal void SetIsPinned()
{
#if WIN32
m_handle = new IntPtr(((int)m_handle) | 1);
#else
m_handle = new IntPtr(((long)m_handle) | 1L);
#endif
}
// Internal native calls that this implementation uses.
[MethodImplAttribute(MethodImplOptions.InternalCall)]
internal static extern IntPtr InternalAlloc(Object value, GCHandleType type);
[MethodImplAttribute(MethodImplOptions.InternalCall)]
internal static extern void InternalFree(IntPtr handle);
[MethodImplAttribute(MethodImplOptions.InternalCall)]
internal static extern Object InternalGet(IntPtr handle);
[MethodImplAttribute(MethodImplOptions.InternalCall)]
internal static extern void InternalSet(IntPtr handle, Object value, bool isPinned);
[MethodImplAttribute(MethodImplOptions.InternalCall)]
internal static extern Object InternalCompareExchange(IntPtr handle, Object value, Object oldValue, bool isPinned);
[MethodImplAttribute(MethodImplOptions.InternalCall)]
internal static extern IntPtr InternalAddrOfPinnedObject(IntPtr handle);
[MethodImplAttribute(MethodImplOptions.InternalCall)]
internal static extern void InternalCheckDomain(IntPtr handle);
// The actual integer handle value that the EE uses internally.
private IntPtr m_handle;
#if MDA_SUPPORTED
// The GCHandle cookie table.
static private GCHandleCookieTable s_cookieTable = null;
static private bool s_probeIsActive = false;
#endif
}
}
// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
// ==++==
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
// ==--==
namespace System.Runtime.InteropServices
{
using System;
using System.Security.Permissions;
using System.Runtime.CompilerServices;
using System.Threading;
// These are the types of handles used by the EE. IMPORTANT: These must
// match the definitions in ObjectHandle.h in the EE.
[Serializable]
[System.Runtime.InteropServices.ComVisible(true)]
public enum GCHandleType
{
Weak = 0,
WeakTrackResurrection = 1,
Normal = 2,
Pinned = 3
}
// This class allows you to create an opaque, GC handle to any
// COM+ object. A GC handle is used when an object reference must be
// reachable from unmanaged memory. There are 3 kinds of roots:
// Normal - keeps the object from being collected.
// Weak - allows object to be collected and handle contents will be zeroed.
// Weak references are zeroed before the finalizer runs, so if the
// object is resurrected in the finalizer the weak reference is
// still zeroed.
// WeakTrackResurrection - Same as weak, but stays until after object is
// really gone.
// Pinned - same as normal, but allows the address of the actual object
// to be taken.
//
[StructLayout(LayoutKind.Sequential)]
[System.Runtime.InteropServices.ComVisible(true)]
public struct GCHandle
{
internal static readonly IntPtr InvalidCookie = new IntPtr(unchecked((int)0xFFFFFFFF));
#if MDA_SUPPORTED
static GCHandle()
{
s_probeIsActive = Mda.IsInvalidGCHandleCookieProbeEnabled();
if (s_probeIsActive)
s_cookieTable = new GCHandleCookieTable();
}
#endif
// Allocate a handle storing the object and the type.
internal GCHandle(Object value, GCHandleType type)
{
m_handle = InternalAlloc(value, type);
// Record if the handle is pinned.
if (type == GCHandleType.Pinned)
SetIsPinned();
}
// Used in the conversion functions below.
internal GCHandle(IntPtr handle)
{
InternalCheckDomain(handle);
m_handle = handle;
}
// Creates a new GC handle for an object.
//
// value - The object that the GC handle is created for.
// type - The type of GC handle to create.
//
// returns a new GC handle that protects the object.
[SecurityPermissionAttribute(SecurityAction.LinkDemand, Flags=SecurityPermissionFlag.UnmanagedCode)]
public static GCHandle Alloc(Object value)
{
return new GCHandle(value, GCHandleType.Normal);
}
[SecurityPermissionAttribute(SecurityAction.LinkDemand, Flags=SecurityPermissionFlag.UnmanagedCode)]
public static GCHandle Alloc(Object value, GCHandleType type)
{
return new GCHandle(value, type);
}
// Frees a GC handle.
[SecurityPermissionAttribute(SecurityAction.LinkDemand, Flags=SecurityPermissionFlag.UnmanagedCode)]
public void Free()
{
// Copy the handle instance member to a local variable. This is required to prevent
// race conditions releasing the handle.
IntPtr handle = m_handle;
// Free the handle if it hasn't already been freed.
if (handle != IntPtr.Zero && Interlocked.CompareExchange(ref m_handle, IntPtr.Zero, handle) == handle)
{
#if WIN32
InternalFree((IntPtr)(((int)handle) & ~1));
#else
InternalFree((IntPtr)(((long)handle) & ~1L));
#endif
#if MDA_SUPPORTED
// If this handle was passed out to unmanaged code, we need to remove it
// from the cookie table.
if (s_probeIsActive)
s_cookieTable.RemoveHandleIfPresent(handle);
#endif
}
else
{
throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_HandleIsNotInitialized"));
}
}
// Target property - allows getting / updating of the handle's referent.
public Object Target
{
[SecurityPermissionAttribute(SecurityAction.LinkDemand, Flags=SecurityPermissionFlag.UnmanagedCode)]
get
{
// Check if the handle was never initialized or was freed.
if (m_handle == IntPtr.Zero)
throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_HandleIsNotInitialized"));
return InternalGet(GetHandleValue());
}
[SecurityPermissionAttribute(SecurityAction.LinkDemand, Flags=SecurityPermissionFlag.UnmanagedCode)]
set
{
// Check if the handle was never initialized or was freed.
if (m_handle == IntPtr.Zero)
throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_HandleIsNotInitialized"));
InternalSet(GetHandleValue(), value, IsPinned());
}
}
// Retrieve the address of an object in a Pinned handle. This throws
// an exception if the handle is any type other than Pinned.
[SecurityPermissionAttribute(SecurityAction.LinkDemand, Flags=SecurityPermissionFlag.UnmanagedCode)]
public IntPtr AddrOfPinnedObject()
{
// Check if the handle was not a pinned handle.
if (!IsPinned())
{
// Check if the handle was never initialized for was freed.
if (m_handle == IntPtr.Zero)
throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_HandleIsNotInitialized"));
// You can only get the address of pinned handles.
throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_HandleIsNotPinned"));
}
// Get the address.
return InternalAddrOfPinnedObject(GetHandleValue());
}
// Determine whether this handle has been allocated or not.
public bool IsAllocated
{
get
{
return m_handle != IntPtr.Zero;
}
}
// Used to create a GCHandle from an int. This is intended to
// be used with the reverse conversion.
[SecurityPermissionAttribute(SecurityAction.LinkDemand, Flags=SecurityPermissionFlag.UnmanagedCode)]
public static explicit operator GCHandle(IntPtr value)
{
return FromIntPtr(value);
}
[SecurityPermissionAttribute(SecurityAction.LinkDemand, Flags=SecurityPermissionFlag.UnmanagedCode)]
public static GCHandle FromIntPtr(IntPtr value)
{
if (value == IntPtr.Zero)
throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_HandleIsNotInitialized"));
IntPtr handle = value;
#if MDA_SUPPORTED
if (s_probeIsActive)
{
// Make sure this cookie matches up with a GCHandle we've passed out a cookie for.
handle = s_cookieTable.GetHandle(value);
if (IntPtr.Zero == handle)
{
// Fire an MDA if we were unable to retrieve the GCHandle.
Mda.FireInvalidGCHandleCookieProbe(value);
return new GCHandle(IntPtr.Zero);
}
}
#endif
return new GCHandle(handle);
}
// Used to get the internal integer representation of the handle out.
public static explicit operator IntPtr(GCHandle value)
{
return ToIntPtr(value);
}
public static IntPtr ToIntPtr(GCHandle value)
{
#if MDA_SUPPORTED
if (s_probeIsActive)
{
// Remember that we passed this GCHandle out by storing the cookie we returned so we
// can later validate.
return s_cookieTable.FindOrAddHandle(value.m_handle);
}
#endif
return value.m_handle;
}
public override int GetHashCode()
{
return (int)m_handle;
}
public override bool Equals(Object o)
{
GCHandle hnd;
// Check that o is a GCHandle first
if(o == null || !(o is GCHandle))
return false;
else
hnd = (GCHandle) o;
return m_handle == hnd.m_handle;
}
public static bool operator ==(GCHandle a, GCHandle b)
{
return a.m_handle == b.m_handle;
}
public static bool operator !=(GCHandle a, GCHandle b)
{
return a.m_handle != b.m_handle;
}
internal IntPtr GetHandleValue()
{
#if WIN32
return new IntPtr(((int)m_handle) & ~1);
#else
return new IntPtr(((long)m_handle) & ~1L);
#endif
}
internal bool IsPinned()
{
#if WIN32
return (((int)m_handle) & 1) != 0;
#else
return (((long)m_handle) & 1) != 0;
#endif
}
internal void SetIsPinned()
{
#if WIN32
m_handle = new IntPtr(((int)m_handle) | 1);
#else
m_handle = new IntPtr(((long)m_handle) | 1L);
#endif
}
// Internal native calls that this implementation uses.
[MethodImplAttribute(MethodImplOptions.InternalCall)]
internal static extern IntPtr InternalAlloc(Object value, GCHandleType type);
[MethodImplAttribute(MethodImplOptions.InternalCall)]
internal static extern void InternalFree(IntPtr handle);
[MethodImplAttribute(MethodImplOptions.InternalCall)]
internal static extern Object InternalGet(IntPtr handle);
[MethodImplAttribute(MethodImplOptions.InternalCall)]
internal static extern void InternalSet(IntPtr handle, Object value, bool isPinned);
[MethodImplAttribute(MethodImplOptions.InternalCall)]
internal static extern Object InternalCompareExchange(IntPtr handle, Object value, Object oldValue, bool isPinned);
[MethodImplAttribute(MethodImplOptions.InternalCall)]
internal static extern IntPtr InternalAddrOfPinnedObject(IntPtr handle);
[MethodImplAttribute(MethodImplOptions.InternalCall)]
internal static extern void InternalCheckDomain(IntPtr handle);
// The actual integer handle value that the EE uses internally.
private IntPtr m_handle;
#if MDA_SUPPORTED
// The GCHandle cookie table.
static private GCHandleCookieTable s_cookieTable = null;
static private bool s_probeIsActive = false;
#endif
}
}
// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
Link Menu

This book is available now!
Buy at Amazon US or
Buy at Amazon UK
- SqlTrackingWorkflowInstance.cs
- StorageBasedPackageProperties.cs
- ActivityTypeCodeDomSerializer.cs
- HtmlTableRowCollection.cs
- FixUp.cs
- ColorAnimationUsingKeyFrames.cs
- SiteOfOriginContainer.cs
- EditCommandColumn.cs
- Tokenizer.cs
- DeclaredTypeValidator.cs
- GlyphInfoList.cs
- HttpConfigurationContext.cs
- XmlQualifiedName.cs
- Crypto.cs
- XmlnsCache.cs
- SystemResourceHost.cs
- BuilderInfo.cs
- ObjectIDGenerator.cs
- ParameterToken.cs
- BoundField.cs
- RefreshEventArgs.cs
- DataSourceGeneratorException.cs
- LineUtil.cs
- XsltFunctions.cs
- RepeatButtonAutomationPeer.cs
- DataGridViewRowContextMenuStripNeededEventArgs.cs
- HMACSHA512.cs
- TreeViewEvent.cs
- PropertyPathWorker.cs
- XPathConvert.cs
- BypassElement.cs
- ArglessEventHandlerProxy.cs
- KnownTypes.cs
- Vector.cs
- ConstraintStruct.cs
- NameTable.cs
- COM2TypeInfoProcessor.cs
- TraceFilter.cs
- DesignerActionUI.cs
- ElementAction.cs
- ResizeGrip.cs
- AudioStateChangedEventArgs.cs
- CatalogPartCollection.cs
- SqlClientMetaDataCollectionNames.cs
- OdbcDataReader.cs
- MeasureData.cs
- DocComment.cs
- FileBasedResourceGroveler.cs
- BitmapEffectInputConnector.cs
- ApplicationInfo.cs
- HtmlWindowCollection.cs
- DataSourceSelectArguments.cs
- DnsPermission.cs
- TableLayoutCellPaintEventArgs.cs
- FacetChecker.cs
- HiddenField.cs
- SqlDataSourceCommandEventArgs.cs
- EncoderParameters.cs
- EditorServiceContext.cs
- XmlLoader.cs
- TreeNodeCollectionEditor.cs
- ExpressionHelper.cs
- DomNameTable.cs
- dsa.cs
- Registry.cs
- TextShapeableCharacters.cs
- ToolStripPanelRenderEventArgs.cs
- CapiHashAlgorithm.cs
- isolationinterop.cs
- FunctionDetailsReader.cs
- PropertyChangedEventManager.cs
- Rect3DConverter.cs
- Relationship.cs
- panel.cs
- KeyedPriorityQueue.cs
- FactoryRecord.cs
- MessageQueue.cs
- HWStack.cs
- QueuedDeliveryRequirementsMode.cs
- NamespaceMapping.cs
- FontCacheUtil.cs
- ObjectItemCollectionAssemblyCacheEntry.cs
- StylusPointProperties.cs
- StatusBarItemAutomationPeer.cs
- Emitter.cs
- BitmapDecoder.cs
- Matrix3DStack.cs
- OperationAbortedException.cs
- PrePostDescendentsWalker.cs
- XAMLParseException.cs
- CurrencyWrapper.cs
- Collection.cs
- FontStretch.cs
- ApplicationFileCodeDomTreeGenerator.cs
- ByteAnimationUsingKeyFrames.cs
- NullableConverter.cs
- MultiSelector.cs
- MemberPathMap.cs
- PackWebRequestFactory.cs
- DataFormats.cs