Terraria v1.4.4.9
Terraria source code documentation
Loading...
Searching...
No Matches
SafeFileHandle.cs
Go to the documentation of this file.
1using System;
4using System.IO;
11
13
15{
17 {
18 private enum Operation : byte
19 {
20 None,
21 Read,
22 Write,
25 }
26
27 private readonly SafeFileHandle _fileHandle;
28
30
32
34
36
37 private long _fileOffset;
38
40
42
44
46
48 {
49 _fileHandle = fileHandle;
50 }
51
52 public ValueTaskSourceStatus GetStatus(short token)
53 {
54 return _source.GetStatus(token);
55 }
56
58 {
59 _source.OnCompleted(continuation, state, token, flags);
60 }
61
62 void IValueTaskSource.GetResult(short token)
63 {
64 GetResult(token);
65 }
66
67 int IValueTaskSource<int>.GetResult(short token)
68 {
69 return (int)GetResult(token);
70 }
71
72 public long GetResult(short token)
73 {
74 try
75 {
76 return _source.GetResult(token);
77 }
78 finally
79 {
80 _source.Reset();
82 }
83 }
84
85 private void ExecuteInternal()
86 {
87 long num = 0L;
88 Exception ex = null;
89 try
90 {
92 {
94 }
95 else
96 {
97 switch (_operation)
98 {
99 case Operation.Read:
100 {
103 break;
104 }
105 case Operation.Write:
107 break;
108 case Operation.ReadScatter:
110 break;
111 case Operation.WriteGather:
113 break;
114 }
115 }
116 }
117 catch (Exception ex2)
118 {
119 ex = ex2;
120 }
121 finally
122 {
123 if (_strategy != null)
124 {
125 if (ex != null)
126 {
128 }
129 else if (_operation == Operation.Read && num != _singleSegment.Length)
130 {
132 }
133 }
134 _operation = Operation.None;
135 _context = null;
136 _strategy = null;
139 _readScatterBuffers = null;
140 _writeGatherBuffers = null;
141 }
142 if (ex == null)
143 {
144 _source.SetResult(num);
145 }
146 else
147 {
149 }
150 }
151
153 {
154 if (_context == null || _context.IsDefault)
155 {
157 return;
158 }
160 {
161 x.ExecuteInternal();
162 }, in this);
163 }
164
170
181
183 {
184 _operation = Operation.Write;
186 _fileOffset = fileOffset;
188 _strategy = strategy;
190 return new ValueTask(this, _source.Version);
191 }
192
202
212 }
213
215 {
216 internal unsafe static readonly IOCompletionCallback s_ioCallback = IOCallback;
217
219
220 internal readonly SafeFileHandle _fileHandle;
221
223
225
226 private int _bufferSize;
227
229
231
233
234 internal ulong _result;
235
236 internal short Version => _source.Version;
237
239 {
240 _fileHandle = fileHandle;
241 _source.RunContinuationsAsynchronously = true;
243 }
244
245 internal void Dispose()
246 {
249 }
250
251 internal static Exception GetIOError(int errorCode, string path)
252 {
253 if (errorCode != 38)
254 {
256 }
258 }
259
260 internal unsafe NativeOverlapped* PrepareForOperation(ReadOnlyMemory<byte> memory, long fileOffset, OSFileStreamStrategy strategy = null)
261 {
262 _result = 0uL;
263 _strategy = strategy;
264 _bufferSize = memory.Length;
265 _memoryHandle = memory.Pin();
267 _overlapped->OffsetLow = (int)fileOffset;
268 _overlapped->OffsetHigh = (int)(fileOffset >> 32);
269 return _overlapped;
270 }
271
273 {
274 return _source.GetStatus(token);
275 }
276
278 {
279 _source.OnCompleted(continuation, state, token, flags);
280 }
281
282 void IValueTaskSource.GetResult(short token)
283 {
284 GetResult(token);
285 }
286
287 public int GetResult(short token)
288 {
289 try
290 {
291 return _source.GetResult(token);
292 }
293 finally
294 {
296 }
297 }
298
300 {
301 if (!cancellationToken.CanBeCanceled)
302 {
303 return;
304 }
305 try
306 {
308 {
310 if (!overlappedValueTaskSource._fileHandle.IsInvalid)
311 {
312 try
313 {
315 }
317 {
318 }
319 }
320 }, this);
321 }
323 {
324 }
325 }
326
327 private unsafe void ReleaseResources()
328 {
329 _strategy = null;
332 if (_overlapped != null)
333 {
335 _overlapped = null;
336 }
337 }
338
339 internal void FinishedScheduling()
340 {
341 ulong num = Interlocked.Exchange(ref _result, 1uL);
342 if (num != 0L)
343 {
344 Complete((uint)num, (uint)(int)(num >> 32) & 0x7FFFFFFFu);
345 }
346 }
347
356
357 internal void Complete(uint errorCode, uint numBytes)
358 {
361 switch (errorCode)
362 {
363 case 0u:
364 case 38u:
365 case 109u:
366 case 232u:
367 if (_bufferSize != numBytes)
368 {
370 }
372 break;
373 case 995u:
374 {
378 break;
379 }
380 default:
383 break;
384 }
385 }
386 }
387
388 private string _path;
389
391
392 private volatile FileOptions _fileOptions = (FileOptions)(-1);
393
394 private volatile int _fileType = -1;
395
397
398 internal string? Path => _path;
399
400 public bool IsAsync => (GetFileOptions() & FileOptions.Asynchronous) != 0;
401
402 internal bool CanSeek
403 {
404 get
405 {
406 if (!base.IsClosed)
407 {
408 return GetFileType() == 1;
409 }
410 return false;
411 }
412 }
413
415
421
426
429 {
430 }
431
432 internal static SafeFileHandle Open(string fullPath, FileMode mode, FileAccess access, FileShare share, FileOptions options, long preallocationSize)
433 {
435 {
437 if (preallocationSize > 0)
438 {
439 Preallocate(fullPath, preallocationSize, safeFileHandle);
440 }
441 if ((options & FileOptions.Asynchronous) != 0)
442 {
443 safeFileHandle.InitThreadPoolBinding();
444 }
445 return safeFileHandle;
446 }
447 }
448
450 {
452 if ((share & FileShare.Inheritable) != 0)
453 {
455 sECURITY_ATTRIBUTES2.nLength = (uint)sizeof(Interop.Kernel32.SECURITY_ATTRIBUTES);
456 sECURITY_ATTRIBUTES2.bInheritHandle = Interop.BOOL.TRUE;
458 }
459 int dwDesiredAccess = (((access & FileAccess.Read) == FileAccess.Read) ? int.MinValue : 0) | (((access & FileAccess.Write) == FileAccess.Write) ? 1073741824 : 0);
460 share &= ~FileShare.Inheritable;
461 if (mode == FileMode.Append)
462 {
463 mode = FileMode.OpenOrCreate;
464 }
465 int num = (int)options;
466 num |= 0x100000;
468 if (safeFileHandle.IsInvalid)
469 {
471 if (num2 == 3 && fullPath.Length == PathInternal.GetRootLength(fullPath))
472 {
473 num2 = 5;
474 }
476 }
477 safeFileHandle._path = fullPath;
478 safeFileHandle._fileOptions = options;
479 return safeFileHandle;
480 }
481
482 private unsafe static void Preallocate(string fullPath, long preallocationSize, SafeFileHandle fileHandle)
483 {
485 fILE_ALLOCATION_INFO.AllocationSize = preallocationSize;
488 {
490 if (lastPInvokeError == 112 || lastPInvokeError == 223)
491 {
492 fileHandle.Dispose();
495 }
496 }
497 }
498
500 {
501 if (IsAsync && ThreadPoolBinding == null)
502 {
503 Init();
504 }
505 void Init()
506 {
507 lock (this)
508 {
509 if (ThreadPoolBinding == null)
510 {
512 }
513 }
514 }
515 }
516
518 {
519 try
520 {
522 }
524 {
525 if (base.OwnsHandle)
526 {
527 Dispose();
528 }
530 }
531 }
532
533 internal unsafe FileOptions GetFileOptions()
534 {
536 if (fileOptions != (FileOptions)(-1))
537 {
538 return fileOptions;
539 }
542 int num = Interop.NtDll.NtQueryInformationFile(this, out IoStatusBlock, &createOptions, 4u, 16u);
543 if (num != 0L)
544 {
545 int errorCode = (int)Interop.NtDll.RtlNtStatusToDosError(num);
547 }
549 if ((createOptions & (Interop.NtDll.CreateOptions)48u) == 0)
550 {
551 fileOptions2 |= FileOptions.Asynchronous;
552 }
553 if ((createOptions & Interop.NtDll.CreateOptions.FILE_WRITE_THROUGH) != 0)
554 {
555 fileOptions2 |= FileOptions.WriteThrough;
556 }
557 if ((createOptions & Interop.NtDll.CreateOptions.FILE_RANDOM_ACCESS) != 0)
558 {
559 fileOptions2 |= FileOptions.RandomAccess;
560 }
561 if ((createOptions & Interop.NtDll.CreateOptions.FILE_SEQUENTIAL_ONLY) != 0)
562 {
563 fileOptions2 |= FileOptions.SequentialScan;
564 }
565 if ((createOptions & Interop.NtDll.CreateOptions.FILE_DELETE_ON_CLOSE) != 0)
566 {
567 fileOptions2 |= FileOptions.DeleteOnClose;
568 }
569 if ((createOptions & Interop.NtDll.CreateOptions.FILE_NO_INTERMEDIATE_BUFFERING) != 0)
570 {
571 fileOptions2 |= (FileOptions)536870912;
572 }
573 return _fileOptions = fileOptions2;
574 }
575
576 internal int GetFileType()
577 {
578 int num = _fileType;
579 if (num == -1)
580 {
581 num = (_fileType = Interop.Kernel32.GetFileType(this));
582 }
583 return num;
584 }
585
590
591 protected override bool ReleaseHandle()
592 {
593 bool result = Interop.Kernel32.CloseHandle(handle);
595 return result;
596 }
597
599 {
600 source._source.Reset();
602 {
603 source._preallocatedOverlapped.Dispose();
604 }
605 }
606}
static unsafe bool CancelIoEx(SafeHandle handle, NativeOverlapped *lpOverlapped)
static unsafe SafeFileHandle CreateFile(string lpFileName, int dwDesiredAccess, FileShare dwShareMode, SECURITY_ATTRIBUTES *lpSecurityAttributes, FileMode dwCreationDisposition, int dwFlagsAndAttributes, IntPtr hTemplateFile)
Definition Interop.cs:105
static bool CloseHandle(IntPtr handle)
static bool DeleteFile(string path)
Definition Interop.cs:750
static unsafe bool SetFileInformationByHandle(SafeFileHandle hFile, int FileInformationClass, void *lpFileInformation, uint dwBufferSize)
static uint GetFileType(IntPtr hFile)
static unsafe int NtQueryInformationFile(SafeFileHandle FileHandle, out IO_STATUS_BLOCK IoStatusBlock, void *FileInformation, uint Length, uint FileInformationClass)
unsafe NativeOverlapped * PrepareForOperation(ReadOnlyMemory< byte > memory, long fileOffset, OSFileStreamStrategy strategy=null)
unsafe void RegisterForCancellation(CancellationToken cancellationToken)
static unsafe void IOCallback(uint errorCode, uint numBytes, NativeOverlapped *pOverlapped)
void OnCompleted(Action< object > continuation, object state, short token, ValueTaskSourceOnCompletedFlags flags)
void OnCompleted(Action< object > continuation, object state, short token, ValueTaskSourceOnCompletedFlags flags)
ValueTask< long > QueueReadScatter(IReadOnlyList< Memory< byte > > buffers, long fileOffset, CancellationToken cancellationToken)
ValueTask< int > QueueRead(Memory< byte > buffer, long fileOffset, CancellationToken cancellationToken, OSFileStreamStrategy strategy)
ValueTask QueueWriteGather(IReadOnlyList< ReadOnlyMemory< byte > > buffers, long fileOffset, CancellationToken cancellationToken)
ValueTask QueueWrite(ReadOnlyMemory< byte > buffer, long fileOffset, CancellationToken cancellationToken, OSFileStreamStrategy strategy)
ThreadPoolValueTaskSource GetThreadPoolValueTaskSource()
static unsafe void Preallocate(string fullPath, long preallocationSize, SafeFileHandle fileHandle)
static unsafe SafeFileHandle CreateFile(string fullPath, FileMode mode, FileAccess access, FileShare share, FileOptions options)
OverlappedValueTaskSource _reusableOverlappedValueTaskSource
static SafeFileHandle Open(string fullPath, FileMode mode, FileAccess access, FileShare share, FileOptions options, long preallocationSize)
OverlappedValueTaskSource GetOverlappedValueTaskSource()
ThreadPoolValueTaskSource _reusableThreadPoolValueTaskSource
void TryToReuse(OverlappedValueTaskSource source)
SafeFileHandle(IntPtr preexistingHandle, bool ownsHandle)
static int GetRootLength(ReadOnlySpan< char > path)
static unsafe void WriteAtOffset(SafeFileHandle handle, ReadOnlySpan< byte > buffer, long fileOffset)
static unsafe int ReadAtOffset(SafeFileHandle handle, Span< byte > buffer, long fileOffset)
static void WriteGatherAtOffset(SafeFileHandle handle, IReadOnlyList< ReadOnlyMemory< byte > > buffers, long fileOffset)
static long ReadScatterAtOffset(SafeFileHandle handle, IReadOnlyList< Memory< byte > > buffers, long fileOffset)
void OnIncompleteOperation(int expectedBytesTransferred, int actualBytesTransferred)
static Exception GetExceptionForWin32Error(int errorCode, string path="")
static string IO_FileTooLarge_Path_AllocationSize
Definition SR.cs:1558
static string Format(string resourceFormat, object p1)
Definition SR.cs:118
static string IO_BindHandleFailed
Definition SR.cs:1560
static string IO_DiskFull_Path_AllocationSize
Definition SR.cs:1556
Definition SR.cs:7
static ? ExecutionContext Capture()
static int CompareExchange(ref int location1, int value, int comparand)
static int Exchange(ref int location1, int value)
static PreAllocatedOverlapped UnsafeCreate(IOCompletionCallback callback, object? state, object? pinData)
static ThreadPoolBoundHandle BindHandle(SafeHandle handle)
unsafe void FreeNativeOverlapped(NativeOverlapped *overlapped)
unsafe NativeOverlapped * AllocateNativeOverlapped(IOCompletionCallback callback, object? state, object? pinData)
static unsafe? object GetNativeOverlappedState(NativeOverlapped *overlapped)
static bool UnsafeQueueUserWorkItem(WaitCallback callBack, object? state)
static void Write(ref bool location, bool value)
Definition Volatile.cs:74
static Exception CreateEndOfFileException()
unsafe delegate void IOCompletionCallback(uint errorCode, uint numBytes, NativeOverlapped *pOVERLAP)
static System.IO.DisableMediaInsertionPrompt Create()
static readonly IntPtr Zero
Definition IntPtr.cs:18
unsafe ReadOnlySpan< T > Span
void OnCompleted(Action< object?> continuation, object? state, short token, ValueTaskSourceOnCompletedFlags flags)