1
// ==++==
2
//
3
//
4
// Copyright (c) 2002 Microsoft Corporation. All rights reserved.
5
//
6
// The use and distribution terms for this software are contained in the file
7
// named license.txt, which can be found in the root of this distribution.
8
// By using this software in any fashion, you are agreeing to be bound by the
9
// terms of this license.
10
//
11
// You must not remove this notice, or any other, from this software.
12
//
13
//
14
// ==--==
15
namespace System.Runtime.InteropServices
{
16
17
using System;
18
using System.Security.Permissions;
19
using System.Runtime.CompilerServices;
20
21
// These are the types of handles used by the EE. IMPORTANT: These must
22
// match the definitions in ObjectHandle.h in the EE.
23
/**//// <include file='doc\GcHandle.uex' path='docs/doc[@for="GCHandleType"]/*' />
24
[Serializable]
25
public enum GCHandleType
26
{
27
/**//// <include file='doc\GcHandle.uex' path='docs/doc[@for="GCHandleType.Weak"]/*' />
28
Weak = 0,
29
/**//// <include file='doc\GcHandle.uex' path='docs/doc[@for="GCHandleType.WeakTrackResurrection"]/*' />
30
WeakTrackResurrection = 1,
31
/**//// <include file='doc\GcHandle.uex' path='docs/doc[@for="GCHandleType.Normal"]/*' />
32
Normal = 2,
33
/**//// <include file='doc\GcHandle.uex' path='docs/doc[@for="GCHandleType.Pinned"]/*' />
34
Pinned = 3
35
}
36
37
// This class allows you to create an opaque, GC handle to any
38
// COM+ object. A GC handle is used when an object reference must be
39
// reachable from unmanaged memory. There are 3 kinds of roots:
40
// Normal - keeps the object from being collected.
41
// Weak - allows object to be collected and handle contents will be zeroed.
42
// Weak references are zeroed before the finalizer runs, so if the
43
// object is resurrected in the finalizer the weak reference is
44
// still zeroed.
45
// WeakTrackResurrection - Same as weak, but stays until after object is
46
// really gone.
47
// Pinned - same as normal, but allows the address of the actual object
48
// to be taken.
49
//
50
/**//// <include file='doc\GcHandle.uex' path='docs/doc[@for="GCHandle"]/*' />
51
[System.Runtime.InteropServices.StructLayout(LayoutKind.Sequential)]
52
public struct GCHandle
53
{
54
// Allocate a handle storing the object and the type.
55
internal GCHandle(Object value, GCHandleType type)
56
{
57
m_handle = InternalAlloc(value, type);
58
59
// Record if the handle is pinned.
60
if (type == GCHandleType.Pinned)
61
SetIsPinned();
62
}
63
64
// Used in the conversion functions below.
65
internal GCHandle(IntPtr handle)
66
{
67
InternalCheckDomain(handle);
68
m_handle = handle;
69
}
70
71
// Creates a new GC handle for an object.
72
//
73
// value - The object that the GC handle is created for.
74
// type - The type of GC handle to create.
75
//
76
// returns a new GC handle that protects the object.
77
/**//// <include file='doc\GcHandle.uex' path='docs/doc[@for="GCHandle.Alloc"]/*' />
78
[SecurityPermissionAttribute(SecurityAction.LinkDemand, Flags=SecurityPermissionFlag.UnmanagedCode)]
79
public static GCHandle Alloc(Object value)
80
{
81
return new GCHandle(value, GCHandleType.Normal);
82
}
83
84
/**//// <include file='doc\GcHandle.uex' path='docs/doc[@for="GCHandle.Alloc1"]/*' />
85
[SecurityPermissionAttribute(SecurityAction.LinkDemand, Flags=SecurityPermissionFlag.UnmanagedCode)]
86
public static GCHandle Alloc(Object value, GCHandleType type)
87
{
88
return new GCHandle(value, type);
89
}
90
91
// Frees a GC handle. The caller must provide synchronization to
92
// prevent multiple threads from executing this simultaneously for
93
// a given handle. If you modify this method please modify the
94
// __InternalFree also which is the internal without the linktime check.
95
/**//// <include file='doc\GcHandle.uex' path='docs/doc[@for="GCHandle.Free"]/*' />
96
[SecurityPermissionAttribute(SecurityAction.LinkDemand, Flags=SecurityPermissionFlag.UnmanagedCode)]
97
public void Free()
98
{
99
// Check if the handle was never initialized for was freed.
100
if (m_handle == IntPtr.Zero)
101
throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_HandleIsNotInitialized"));
102
103
// Free the handle.
104
InternalFree(GetHandleValue());
105
m_handle = IntPtr.Zero;
106
}
107
108
internal void __InternalFree()
109
{
110
// Check if the handle was never initialized for was freed.
111
if (m_handle == IntPtr.Zero)
112
throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_HandleIsNotInitialized"));
113
114
// Free the handle.
115
InternalFree(GetHandleValue());
116
m_handle = IntPtr.Zero;
117
}
118
119
// Target property - allows getting / updating of the handle's referent. If you modify this method
120
121
// then modify the __InternalTarget too which is the internal method without the linktime check.
122
/**//// <include file='doc\GcHandle.uex' path='docs/doc[@for="GCHandle.Target"]/*' />
123
public Object Target
124
{
125
[SecurityPermissionAttribute(SecurityAction.LinkDemand, Flags=SecurityPermissionFlag.UnmanagedCode)]
126
get
127
{
128
// Check if the handle was never initialized or was freed.
129
if (m_handle == IntPtr.Zero)
130
throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_HandleIsNotInitialized"));
131
132
return InternalGet(GetHandleValue());
133
}
134
135
[SecurityPermissionAttribute(SecurityAction.LinkDemand, Flags=SecurityPermissionFlag.UnmanagedCode)]
136
set
137
{
138
// Check if the handle was never initialized or was freed.
139
if (m_handle == IntPtr.Zero)
140
throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_HandleIsNotInitialized"));
141
142
InternalSet(GetHandleValue(), value, IsPinned());
143
}
144
}
145
146
internal Object __InternalTarget
147
{
148
get
149
{
150
// Check if the handle was never initialized or was freed.
151
if (m_handle == IntPtr.Zero)
152
throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_HandleIsNotInitialized"));
153
154
return InternalGet(GetHandleValue());
155
}
156
}
157
158
// Retrieve the address of an object in a Pinned handle. This throws
159
// an exception if the handle is any type other than Pinned.
160
/**//// <include file='doc\GcHandle.uex' path='docs/doc[@for="GCHandle.AddrOfPinnedObject"]/*' />
161
[SecurityPermissionAttribute(SecurityAction.LinkDemand, Flags=SecurityPermissionFlag.UnmanagedCode)]
162
public IntPtr AddrOfPinnedObject()
163
{
164
// Check if the handle was not a pinned handle.
165
if (!IsPinned())
166
{
167
// Check if the handle was never initialized for was freed.
168
if (m_handle == IntPtr.Zero)
169
throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_HandleIsNotInitialized"));
170
171
// You can only get the address of pinned handles.
172
throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_HandleIsNotPinned"));
173
}
174
175
// Get the address.
176
return InternalAddrOfPinnedObject(GetHandleValue());
177
}
178
179
// Determine whether this handle has been allocated or not.
180
/**//// <include file='doc\GcHandle.uex' path='docs/doc[@for="GCHandle.IsAllocated"]/*' />
181
public bool IsAllocated
182
{
183
get
184
{
185
return m_handle != IntPtr.Zero;
186
}
187
}
188
189
// Used to create a GCHandle from an int. This is intended to
190
// be used with the reverse conversion.
191
/**//// <include file='doc\GcHandle.uex' path='docs/doc[@for="GCHandle.operatorGCHandle"]/*' />
192
[SecurityPermissionAttribute(SecurityAction.LinkDemand, Flags=SecurityPermissionFlag.UnmanagedCode)]
193
public static explicit operator GCHandle(IntPtr value)
194
{
195
return new GCHandle(value);
196
}
197
198
// Used to get the internal integer representation of the handle out.
199
/**//// <include file='doc\GcHandle.uex' path='docs/doc[@for="GCHandle.operatorIntPtr"]/*' />
200
public static explicit operator IntPtr(GCHandle value)
201
{
202
return value.m_handle;
203
}
204
205
internal IntPtr GetHandleValue()
206
{
207
#if WIN32
208
return new IntPtr(((int)m_handle) & ~1);
209
#else
210
return new IntPtr(((long)m_handle) & ~1L);
211
#endif
212
}
213
214
internal bool IsPinned()
215
{
216
#if WIN32
217
return (((int)m_handle) & 1) != 0;
218
#else
219
return (((long)m_handle) & 1) != 0;
220
#endif
221
}
222
223
internal void SetIsPinned()
224
{
225
#if WIN32
226
m_handle = new IntPtr(((int)m_handle) | 1);
227
#else
228
m_handle = new IntPtr(((long)m_handle) | 1L);
229
#endif
230
}
231
232
// Internal native calls that this implementation uses.
233
[MethodImplAttribute(MethodImplOptions.InternalCall)]
234
internal static extern IntPtr InternalAlloc(Object value, GCHandleType type);
235
[MethodImplAttribute(MethodImplOptions.InternalCall)]
236
internal static extern void InternalFree(IntPtr handle);
237
[MethodImplAttribute(MethodImplOptions.InternalCall)]
238
internal static extern Object InternalGet(IntPtr handle);
239
[MethodImplAttribute(MethodImplOptions.InternalCall)]
240
internal static extern void InternalSet(IntPtr handle, Object value, bool isPinned);
241
[MethodImplAttribute(MethodImplOptions.InternalCall)]
242
internal static extern void InternalCompareExchange(IntPtr handle, Object value, Object oldValue, bool isPinned);
243
[MethodImplAttribute(MethodImplOptions.InternalCall)]
244
internal static extern IntPtr InternalAddrOfPinnedObject(IntPtr handle);
245
[MethodImplAttribute(MethodImplOptions.InternalCall)]
246
internal static extern void InternalCheckDomain(IntPtr handle);
247
248
249
// The actual integer handle value that the EE uses internally.
250
private IntPtr m_handle;
251
}
252
}
253
254

2

3

4

5

6

7

8

9

10

11

12

13

14

15



16

17

18

19

20

21

22

23


24

25

26



27


28

29


30

31


32

33


34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50


51

52

53



54

55

56



57

58

59

60

61

62

63

64

65

66



67

68

69

70

71

72

73

74

75

76

77


78

79

80



81

82

83

84


85

86

87



88

89

90

91

92

93

94

95


96

97

98



99

100

101

102

103

104

105

106

107

108

109



110

111

112

113

114

115

116

117

118

119

120

121

122


123

124



125

126

127



128

129

130

131

132

133

134

135

136

137



138

139

140

141

142

143

144

145

146

147



148

149



150

151

152

153

154

155

156

157

158

159

160


161

162

163



164

165

166



167

168

169

170

171

172

173

174

175

176

177

178

179

180


181

182



183

184



185

186

187

188

189

190

191


192

193

194



195

196

197

198

199


200

201



202

203

204

205

206



207

208

209

210

211

212

213

214

215



216

217

218

219

220

221

222

223

224



225

226

227

228

229

230

231

232

233

234

235

236

237

238

239

240

241

242

243

244

245

246

247

248

249

250

251

252

253

254
