Terraria v1.4.4.9
Terraria source code documentation
Loading...
Searching...
No Matches
SecureString.cs
Go to the documentation of this file.
4
5namespace System.Security;
6
7public sealed class SecureString : IDisposable
8{
9 private sealed class UnmanagedBuffer : SafeBuffer
10 {
11 private int _byteLength;
12
14 : base(ownsHandle: true)
15 {
16 }
17
18 public static UnmanagedBuffer Allocate(int byteLength)
19 {
20 UnmanagedBuffer unmanagedBuffer = new UnmanagedBuffer();
21 unmanagedBuffer.SetHandle(Marshal.AllocHGlobal(byteLength));
22 unmanagedBuffer.Initialize((ulong)byteLength);
23 unmanagedBuffer._byteLength = byteLength;
24 return unmanagedBuffer;
25 }
26
27 internal unsafe static void Copy(UnmanagedBuffer source, UnmanagedBuffer destination, ulong bytesLength)
28 {
29 if (bytesLength == 0L)
30 {
31 return;
32 }
33 byte* pointer = null;
34 byte* pointer2 = null;
35 try
36 {
37 source.AcquirePointer(ref pointer);
38 destination.AcquirePointer(ref pointer2);
39 Buffer.MemoryCopy(pointer, pointer2, destination.ByteLength, bytesLength);
40 }
41 finally
42 {
43 if (pointer2 != null)
44 {
45 destination.ReleasePointer();
46 }
47 if (pointer != null)
48 {
49 source.ReleasePointer();
50 }
51 }
52 }
53
54 protected unsafe override bool ReleaseHandle()
55 {
56 new Span<byte>((void*)handle, _byteLength).Clear();
58 return true;
59 }
60 }
61
62 private readonly object _methodLock = new object();
63
65
66 private int _decryptedLength;
67
68 private bool _encrypted;
69
70 private bool _readOnly;
71
72 public int Length
73 {
74 get
75 {
77 return Volatile.Read(ref _decryptedLength);
78 }
79 }
80
85
86 [CLSCompliant(false)]
87 public unsafe SecureString(char* value, int length)
88 {
89 if (value == null)
90 {
91 throw new ArgumentNullException("value");
92 }
93 if (length < 0)
94 {
96 }
97 if (length > 65536)
98 {
100 }
102 }
103
105 {
107 _decryptedLength = value.Length;
108 SafeBuffer bufferToRelease = null;
109 try
110 {
111 Span<char> destination = AcquireSpan(ref bufferToRelease);
112 value.CopyTo(destination);
113 }
114 finally
115 {
117 bufferToRelease?.DangerousRelease();
118 }
119 }
120
122 {
123 _buffer = UnmanagedBuffer.Allocate((int)str._buffer.ByteLength);
124 UnmanagedBuffer.Copy(str._buffer, _buffer, str._buffer.ByteLength);
125 _decryptedLength = str._decryptedLength;
126 _encrypted = str._encrypted;
127 }
128
129 private void EnsureCapacity(int capacity)
130 {
131 if (capacity > 65536)
132 {
134 }
135 if ((uint)(capacity * 2) > _buffer.ByteLength)
136 {
139 UnmanagedBuffer.Copy(buffer, unmanagedBuffer, (uint)(_decryptedLength * 2));
140 _buffer = unmanagedBuffer;
141 buffer.Dispose();
142 }
143 }
144
145 public void AppendChar(char c)
146 {
147 lock (_methodLock)
148 {
151 SafeBuffer bufferToRelease = null;
152 try
153 {
156 AcquireSpan(ref bufferToRelease)[_decryptedLength] = c;
158 }
159 finally
160 {
162 bufferToRelease?.DangerousRelease();
163 }
164 }
165 }
166
167 public void Clear()
168 {
169 lock (_methodLock)
170 {
174 SafeBuffer bufferToRelease = null;
175 try
176 {
177 AcquireSpan(ref bufferToRelease).Clear();
178 }
179 finally
180 {
181 bufferToRelease?.DangerousRelease();
182 }
183 }
184 }
185
187 {
188 lock (_methodLock)
189 {
191 return new SecureString(this);
192 }
193 }
194
195 public void Dispose()
196 {
197 lock (_methodLock)
198 {
199 if (_buffer != null)
200 {
202 _buffer = null;
203 }
204 }
205 }
206
207 public void InsertAt(int index, char c)
208 {
209 lock (_methodLock)
210 {
211 if (index < 0 || index > _decryptedLength)
212 {
214 }
217 SafeBuffer bufferToRelease = null;
218 try
219 {
222 Span<char> span = AcquireSpan(ref bufferToRelease);
223 span.Slice(index, _decryptedLength - index).CopyTo(span.Slice(index + 1));
224 span[index] = c;
226 }
227 finally
228 {
230 bufferToRelease?.DangerousRelease();
231 }
232 }
233 }
234
235 public bool IsReadOnly()
236 {
238 return Volatile.Read(ref _readOnly);
239 }
240
241 public void MakeReadOnly()
242 {
244 Volatile.Write(ref _readOnly, value: true);
245 }
246
247 public void RemoveAt(int index)
248 {
249 lock (_methodLock)
250 {
251 if (index < 0 || index >= _decryptedLength)
252 {
254 }
257 SafeBuffer bufferToRelease = null;
258 try
259 {
261 Span<char> span = AcquireSpan(ref bufferToRelease);
262 span.Slice(index + 1, _decryptedLength - (index + 1)).CopyTo(span.Slice(index));
264 }
265 finally
266 {
268 bufferToRelease?.DangerousRelease();
269 }
270 }
271 }
272
273 public void SetAt(int index, char c)
274 {
275 lock (_methodLock)
276 {
277 if (index < 0 || index >= _decryptedLength)
278 {
280 }
283 SafeBuffer bufferToRelease = null;
284 try
285 {
287 AcquireSpan(ref bufferToRelease)[index] = c;
288 }
289 finally
290 {
292 bufferToRelease?.DangerousRelease();
293 }
294 }
295 }
296
297 private unsafe Span<char> AcquireSpan(ref SafeBuffer bufferToRelease)
298 {
300 bool success = false;
301 buffer.DangerousAddRef(ref success);
302 bufferToRelease = buffer;
303 return new Span<char>((void*)buffer.DangerousGetHandle(), (int)(buffer.ByteLength / 2));
304 }
305
306 private void EnsureNotReadOnly()
307 {
308 if (_readOnly)
309 {
311 }
312 }
313
314 private void EnsureNotDisposed()
315 {
316 if (_buffer == null)
317 {
318 throw new ObjectDisposedException(GetType().Name);
319 }
320 }
321
322 internal unsafe IntPtr MarshalToBSTR()
323 {
324 lock (_methodLock)
325 {
328 SafeBuffer bufferToRelease = null;
329 IntPtr intPtr = IntPtr.Zero;
330 int length = 0;
331 try
332 {
333 Span<char> span = AcquireSpan(ref bufferToRelease);
335 intPtr = Marshal.AllocBSTR(length);
336 span.Slice(0, length).CopyTo(new Span<char>((void*)intPtr, length));
337 IntPtr result = intPtr;
338 intPtr = IntPtr.Zero;
339 return result;
340 }
341 finally
342 {
343 if (intPtr != IntPtr.Zero)
344 {
345 new Span<char>((void*)intPtr, length).Clear();
346 Marshal.FreeBSTR(intPtr);
347 }
349 bufferToRelease?.DangerousRelease();
350 }
351 }
352 }
353
354 internal unsafe IntPtr MarshalToString(bool globalAlloc, bool unicode)
355 {
356 lock (_methodLock)
357 {
360 SafeBuffer bufferToRelease = null;
361 IntPtr intPtr = IntPtr.Zero;
362 int num = 0;
363 try
364 {
365 Span<char> span = AcquireSpan(ref bufferToRelease).Slice(0, _decryptedLength);
366 num = ((!unicode) ? Marshal.GetAnsiStringByteCount(span) : ((span.Length + 1) * 2));
367 intPtr = ((!globalAlloc) ? Marshal.AllocCoTaskMem(num) : Marshal.AllocHGlobal(num));
368 if (unicode)
369 {
370 Span<char> destination = new Span<char>((void*)intPtr, num / 2);
371 span.CopyTo(destination);
372 destination[destination.Length - 1] = '\0';
373 }
374 else
375 {
376 Marshal.GetAnsiStringBytes(span, new Span<byte>((void*)intPtr, num));
377 }
378 IntPtr result = intPtr;
379 intPtr = IntPtr.Zero;
380 return result;
381 }
382 finally
383 {
384 if (intPtr != IntPtr.Zero)
385 {
386 new Span<byte>((void*)intPtr, num).Clear();
387 if (globalAlloc)
388 {
389 Marshal.FreeHGlobal(intPtr);
390 }
391 else
392 {
393 Marshal.FreeCoTaskMem(intPtr);
394 }
395 }
397 bufferToRelease?.DangerousRelease();
398 }
399 }
400 }
401
402 private static int GetAlignedByteSize(int length)
403 {
404 int num = Math.Max(length, 1) * 2;
405 return (num + 15) / 16 * 16;
406 }
407
408 private void ProtectMemory()
409 {
411 {
413 }
414 _encrypted = true;
415 }
416
417 private void UnprotectMemory()
418 {
420 {
422 }
423 _encrypted = false;
424 }
425}
static bool CryptUnprotectMemory(SafeBuffer pData, uint cbData, uint dwFlags)
static bool CryptProtectMemory(SafeBuffer pData, uint cbData, uint dwFlags)
static unsafe void MemoryCopy(void *source, void *destination, long destinationSizeInBytes, long sourceBytesToCopy)
Definition Buffer.cs:195
static byte Max(byte val1, byte val2)
Definition Math.cs:738
static IntPtr AllocBSTR(int length)
Definition Marshal.cs:1730
static void FreeHGlobal(IntPtr hglobal)
Definition Marshal.cs:1680
static void FreeCoTaskMem(IntPtr ptr)
Definition Marshal.cs:1712
static unsafe int GetAnsiStringByteCount(ReadOnlySpan< char > chars)
Definition Marshal.cs:1625
static IntPtr AllocCoTaskMem(int cb)
Definition Marshal.cs:1702
static unsafe void GetAnsiStringBytes(ReadOnlySpan< char > chars, Span< byte > bytes)
Definition Marshal.cs:1646
static IntPtr AllocHGlobal(int cb)
Definition Marshal.cs:625
static void FreeBSTR(IntPtr ptr)
Definition Marshal.cs:1750
void DangerousAddRef(ref bool success)
Definition SafeHandle.cs:76
static string ArgumentOutOfRange_Capacity
Definition SR.cs:984
static string ArgumentOutOfRange_IndexString
Definition SR.cs:1036
static string ArgumentOutOfRange_Length
Definition SR.cs:1048
static string InvalidOperation_ReadOnly
Definition SR.cs:1504
static string ArgumentOutOfRange_NeedNonNegNum
Definition SR.cs:32
Definition SR.cs:7
static unsafe void Copy(UnmanagedBuffer source, UnmanagedBuffer destination, ulong bytesLength)
static UnmanagedBuffer Allocate(int byteLength)
void InsertAt(int index, char c)
void SetAt(int index, char c)
static int GetAlignedByteSize(int length)
unsafe SecureString(char *value, int length)
unsafe IntPtr MarshalToString(bool globalAlloc, bool unicode)
unsafe Span< char > AcquireSpan(ref SafeBuffer bufferToRelease)
void Initialize(ReadOnlySpan< char > value)
void EnsureCapacity(int capacity)
SecureString(SecureString str)
static bool Read(ref bool location)
Definition Volatile.cs:67
static void Write(ref bool location, bool value)
Definition Volatile.cs:74
static readonly IntPtr Zero
Definition IntPtr.cs:18
void CopyTo(Span< T > destination)
Definition Span.cs:224
Span< T > Slice(int start)
Definition Span.cs:271
unsafe void Clear()
Definition Span.cs:198