mscorlib(4.0.0.0) API with additions
GCHandle.cs
2 using System.Security;
3 using System.Threading;
4 
6 {
8  [ComVisible(true)]
9  [__DynamicallyInvokable]
10  public struct GCHandle
11  {
12  private const GCHandleType MaxHandleType = GCHandleType.Pinned;
13 
14  private IntPtr m_handle;
15 
16  private static volatile GCHandleCookieTable s_cookieTable;
17 
18  private static volatile bool s_probeIsActive;
19 
23  [__DynamicallyInvokable]
24  public object Target
25  {
26  [SecurityCritical]
27  [__DynamicallyInvokable]
28  get
29  {
30  if (m_handle == IntPtr.Zero)
31  {
32  throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_HandleIsNotInitialized"));
33  }
34  return InternalGet(GetHandleValue());
35  }
36  [SecurityCritical]
37  [__DynamicallyInvokable]
38  set
39  {
40  if (m_handle == IntPtr.Zero)
41  {
42  throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_HandleIsNotInitialized"));
43  }
44  InternalSet(GetHandleValue(), value, IsPinned());
45  }
46  }
47 
51  [__DynamicallyInvokable]
52  public bool IsAllocated
53  {
54  [__DynamicallyInvokable]
55  get
56  {
57  return m_handle != IntPtr.Zero;
58  }
59  }
60 
61  [SecuritySafeCritical]
62  static GCHandle()
63  {
64  s_probeIsActive = Mda.IsInvalidGCHandleCookieProbeEnabled();
65  if (s_probeIsActive)
66  {
67  s_cookieTable = new GCHandleCookieTable();
68  }
69  }
70 
71  [SecurityCritical]
72  internal GCHandle(object value, GCHandleType type)
73  {
74  if ((uint)type > 3u)
75  {
76  throw new ArgumentOutOfRangeException("type", Environment.GetResourceString("ArgumentOutOfRange_Enum"));
77  }
78  m_handle = InternalAlloc(value, type);
79  if (type == GCHandleType.Pinned)
80  {
81  SetIsPinned();
82  }
83  }
84 
85  [SecurityCritical]
86  internal GCHandle(IntPtr handle)
87  {
88  InternalCheckDomain(handle);
89  m_handle = handle;
90  }
91 
96  [SecurityCritical]
97  [__DynamicallyInvokable]
98  public static GCHandle Alloc(object value)
99  {
100  return new GCHandle(value, GCHandleType.Normal);
101  }
102 
108  [SecurityCritical]
109  [__DynamicallyInvokable]
110  public static GCHandle Alloc(object value, GCHandleType type)
111  {
112  return new GCHandle(value, type);
113  }
114 
117  [SecurityCritical]
118  [__DynamicallyInvokable]
119  public void Free()
120  {
121  IntPtr handle = m_handle;
122  if (handle != IntPtr.Zero && Interlocked.CompareExchange(ref m_handle, IntPtr.Zero, handle) == handle)
123  {
124  if (s_probeIsActive)
125  {
126  s_cookieTable.RemoveHandleIfPresent(handle);
127  }
128  InternalFree((IntPtr)((long)handle & -2));
129  return;
130  }
131  throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_HandleIsNotInitialized"));
132  }
133 
137  [SecurityCritical]
139  {
140  if (!IsPinned())
141  {
142  if (m_handle == IntPtr.Zero)
143  {
144  throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_HandleIsNotInitialized"));
145  }
146  throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_HandleIsNotPinned"));
147  }
148  return InternalAddrOfPinnedObject(GetHandleValue());
149  }
150 
154  [SecurityCritical]
155  public static explicit operator GCHandle(IntPtr value)
156  {
157  return FromIntPtr(value);
158  }
159 
164  [SecurityCritical]
165  public static GCHandle FromIntPtr(IntPtr value)
166  {
167  if (value == IntPtr.Zero)
168  {
169  throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_HandleIsNotInitialized"));
170  }
171  IntPtr intPtr = value;
172  if (s_probeIsActive)
173  {
174  intPtr = s_cookieTable.GetHandle(value);
175  if (IntPtr.Zero == intPtr)
176  {
177  Mda.FireInvalidGCHandleCookieProbe(value);
178  return new GCHandle(IntPtr.Zero);
179  }
180  }
181  return new GCHandle(intPtr);
182  }
183 
187  public static explicit operator IntPtr(GCHandle value)
188  {
189  return ToIntPtr(value);
190  }
191 
195  public static IntPtr ToIntPtr(GCHandle value)
196  {
197  if (s_probeIsActive)
198  {
199  return s_cookieTable.FindOrAddHandle(value.m_handle);
200  }
201  return value.m_handle;
202  }
203 
206  [__DynamicallyInvokable]
207  public override int GetHashCode()
208  {
209  return m_handle.GetHashCode();
210  }
211 
216  [__DynamicallyInvokable]
217  public override bool Equals(object o)
218  {
219  if (o == null || !(o is GCHandle))
220  {
221  return false;
222  }
223  GCHandle gCHandle = (GCHandle)o;
224  return m_handle == gCHandle.m_handle;
225  }
226 
232  [__DynamicallyInvokable]
233  public static bool operator ==(GCHandle a, GCHandle b)
234  {
235  return a.m_handle == b.m_handle;
236  }
237 
243  [__DynamicallyInvokable]
244  public static bool operator !=(GCHandle a, GCHandle b)
245  {
246  return a.m_handle != b.m_handle;
247  }
248 
249  internal IntPtr GetHandleValue()
250  {
251  return new IntPtr((long)m_handle & -2);
252  }
253 
254  internal bool IsPinned()
255  {
256  return ((long)m_handle & 1) != 0;
257  }
258 
259  internal void SetIsPinned()
260  {
261  m_handle = new IntPtr((long)m_handle | 1);
262  }
263 
264  [MethodImpl(MethodImplOptions.InternalCall)]
265  [SecurityCritical]
266  internal static extern IntPtr InternalAlloc(object value, GCHandleType type);
267 
268  [MethodImpl(MethodImplOptions.InternalCall)]
269  [SecurityCritical]
270  internal static extern void InternalFree(IntPtr handle);
271 
272  [MethodImpl(MethodImplOptions.InternalCall)]
273  [SecurityCritical]
274  internal static extern object InternalGet(IntPtr handle);
275 
276  [MethodImpl(MethodImplOptions.InternalCall)]
277  [SecurityCritical]
278  internal static extern void InternalSet(IntPtr handle, object value, bool isPinned);
279 
280  [MethodImpl(MethodImplOptions.InternalCall)]
281  [SecurityCritical]
282  internal static extern object InternalCompareExchange(IntPtr handle, object value, object oldValue, bool isPinned);
283 
284  [MethodImpl(MethodImplOptions.InternalCall)]
285  [SecurityCritical]
286  internal static extern IntPtr InternalAddrOfPinnedObject(IntPtr handle);
287 
288  [MethodImpl(MethodImplOptions.InternalCall)]
289  [SecurityCritical]
290  internal static extern void InternalCheckDomain(IntPtr handle);
291 
292  [MethodImpl(MethodImplOptions.InternalCall)]
293  [SecurityCritical]
294  internal static extern GCHandleType InternalGetHandleType(IntPtr handle);
295  }
296 }
static bool operator !=(GCHandle a, GCHandle b)
Returns a value indicating whether two T:System.Runtime.InteropServices.GCHandle objects are not equa...
Definition: GCHandle.cs:244
Definition: __Canon.cs:3
The exception that is thrown when the value of an argument is outside the allowable range of values a...
override bool Equals(object o)
Determines whether the specified T:System.Runtime.InteropServices.GCHandle object is equal to the cur...
Definition: GCHandle.cs:217
bool IsAllocated
Gets a value indicating whether the handle is allocated.
Definition: GCHandle.cs:53
Provides information about, and means to manipulate, the current environment and platform....
Definition: Environment.cs:21
override int GetHashCode()
Returns an identifier for the current T:System.Runtime.InteropServices.GCHandle object.
Definition: GCHandle.cs:207
static int CompareExchange(ref int location1, int value, int comparand)
Compares two 32-bit signed integers for equality and, if they are equal, replaces the first value.
Indicates that a modified instance is pinned in memory. This class cannot be inherited.
Definition: IsPinned.cs:4
A platform-specific type that is used to represent a pointer or a handle.
Definition: IntPtr.cs:14
static GCHandle Alloc(object value)
Allocates a F:System.Runtime.InteropServices.GCHandleType.Normal handle for the specified object.
Definition: GCHandle.cs:98
GCHandleType
Represents the types of handles the T:System.Runtime.InteropServices.GCHandle class can allocate.
Definition: GCHandleType.cs:7
static GCHandle Alloc(object value, GCHandleType type)
Allocates a handle of the specified type for the specified object.
Definition: GCHandle.cs:110
Provides a way to access a managed object from unmanaged memory.
Definition: GCHandle.cs:10
IntPtr AddrOfPinnedObject()
Retrieves the address of an object in a F:System.Runtime.InteropServices.GCHandleType....
Definition: GCHandle.cs:138
MethodImplOptions
Defines the details of how a method is implemented.
void Free()
Releases a T:System.Runtime.InteropServices.GCHandle.
Definition: GCHandle.cs:119
static IntPtr ToIntPtr(GCHandle value)
Returns the internal integer representation of a T:System.Runtime.InteropServices....
Definition: GCHandle.cs:195
static bool operator==(GCHandle a, GCHandle b)
Returns a value indicating whether two T:System.Runtime.InteropServices.GCHandle objects are equal.
Definition: GCHandle.cs:233
static readonly IntPtr Zero
A read-only field that represents a pointer or handle that has been initialized to zero.
Definition: IntPtr.cs:20
The exception that is thrown when a method call is invalid for the object's current state.
Provides atomic operations for variables that are shared by multiple threads.
Definition: Interlocked.cs:10
static GCHandle FromIntPtr(IntPtr value)
Returns a new T:System.Runtime.InteropServices.GCHandle object created from a handle to a managed obj...
Definition: GCHandle.cs:165
unsafe override int GetHashCode()
Returns the hash code for this instance.
Definition: IntPtr.cs:123
object Target
Gets or sets the object this handle represents.
Definition: GCHandle.cs:25