Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/mono/corert.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'src/System.Private.CoreLib/shared/System/IO/FileStream.Win32.cs')
-rw-r--r--src/System.Private.CoreLib/shared/System/IO/FileStream.Win32.cs58
1 files changed, 58 insertions, 0 deletions
diff --git a/src/System.Private.CoreLib/shared/System/IO/FileStream.Win32.cs b/src/System.Private.CoreLib/shared/System/IO/FileStream.Win32.cs
index 4b75ad6da..edcf8e546 100644
--- a/src/System.Private.CoreLib/shared/System/IO/FileStream.Win32.cs
+++ b/src/System.Private.CoreLib/shared/System/IO/FileStream.Win32.cs
@@ -2,6 +2,7 @@
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
+using System.Diagnostics;
using Microsoft.Win32.SafeHandles;
namespace System.IO
@@ -43,5 +44,62 @@ namespace System.IO
Interop.Kernel32.CreateFile(_path, fAccess, share, ref secAttrs, mode, flagsAndAttributes, IntPtr.Zero));
}
}
+
+ private static bool GetDefaultIsAsync(SafeFileHandle handle)
+ {
+ return handle.IsAsync ?? !IsHandleSynchronous(handle, ignoreInvalid: true) ?? DefaultIsAsync;
+ }
+
+ private static unsafe bool? IsHandleSynchronous(SafeFileHandle fileHandle, bool ignoreInvalid)
+ {
+ if (fileHandle.IsInvalid)
+ return null;
+
+ uint fileMode;
+
+ int status = Interop.NtDll.NtQueryInformationFile(
+ FileHandle: fileHandle,
+ IoStatusBlock: out Interop.NtDll.IO_STATUS_BLOCK ioStatus,
+ FileInformation: &fileMode,
+ Length: sizeof(uint),
+ FileInformationClass: Interop.NtDll.FileModeInformation);
+
+ switch (status)
+ {
+ case 0:
+ // We we're successful
+ break;
+ case Interop.NtDll.STATUS_INVALID_HANDLE:
+ if (!ignoreInvalid)
+ {
+ throw Win32Marshal.GetExceptionForWin32Error(Interop.Errors.ERROR_INVALID_HANDLE);
+ }
+ else
+ {
+ return null;
+ }
+ default:
+ // Something else is preventing access
+ Debug.Fail("Unable to get the file mode information, status was" + status.ToString());
+ return null;
+ }
+
+ // If either of these two flags are set, the file handle is synchronous (not overlapped)
+ return (fileMode & (Interop.NtDll.FILE_SYNCHRONOUS_IO_ALERT | Interop.NtDll.FILE_SYNCHRONOUS_IO_NONALERT)) > 0;
+ }
+
+ private static void VerifyHandleIsSync(SafeFileHandle handle, int fileType, FileAccess access)
+ {
+ // As we can accurately check the handle type when we have access to NtQueryInformationFile we don't need to skip for
+ // any particular file handle type.
+
+ // If the handle was passed in without an explicit async setting, we already looked it up in GetDefaultIsAsync
+ if (!handle.IsAsync.HasValue)
+ return;
+
+ // If we can't check the handle, just assume it is ok.
+ if (!(IsHandleSynchronous(handle, ignoreInvalid: false) ?? true))
+ throw new ArgumentException(SR.Arg_HandleNotSync, nameof(handle));
+ }
}
}