diff options
Diffstat (limited to 'src/mscorlib/shared/System/IO/FileStream.Win32.cs')
-rw-r--r-- | src/mscorlib/shared/System/IO/FileStream.Win32.cs | 77 |
1 files changed, 77 insertions, 0 deletions
diff --git a/src/mscorlib/shared/System/IO/FileStream.Win32.cs b/src/mscorlib/shared/System/IO/FileStream.Win32.cs new file mode 100644 index 0000000000..0045ebeaf8 --- /dev/null +++ b/src/mscorlib/shared/System/IO/FileStream.Win32.cs @@ -0,0 +1,77 @@ +// Licensed to the .NET Foundation under one or more agreements. +// 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.Buffers; +using System.Diagnostics; +using System.Runtime.InteropServices; +using System.Threading; +using System.Threading.Tasks; +using Microsoft.Win32.SafeHandles; +using System.Runtime.CompilerServices; + +namespace System.IO +{ + public partial class FileStream : Stream + { + private SafeFileHandle OpenHandle(FileMode mode, FileShare share, FileOptions options) + { + Interop.Kernel32.SECURITY_ATTRIBUTES secAttrs = GetSecAttrs(share); + + int fAccess = + ((_access & FileAccess.Read) == FileAccess.Read ? GENERIC_READ : 0) | + ((_access & FileAccess.Write) == FileAccess.Write ? GENERIC_WRITE : 0); + + // Our Inheritable bit was stolen from Windows, but should be set in + // the security attributes class. Don't leave this bit set. + share &= ~FileShare.Inheritable; + + // Must use a valid Win32 constant here... + if (mode == FileMode.Append) + mode = FileMode.OpenOrCreate; + + int flagsAndAttributes = (int)options; + + // For mitigating local elevation of privilege attack through named pipes + // make sure we always call CreateFile with SECURITY_ANONYMOUS so that the + // named pipe server can't impersonate a high privileged client security context + flagsAndAttributes |= (Interop.Kernel32.SecurityOptions.SECURITY_SQOS_PRESENT | Interop.Kernel32.SecurityOptions.SECURITY_ANONYMOUS); + + // Don't pop up a dialog for reading from an empty floppy drive + uint oldMode = Interop.Kernel32.SetErrorMode(Interop.Kernel32.SEM_FAILCRITICALERRORS); + try + { + SafeFileHandle fileHandle = Interop.Kernel32.CreateFile(_path, fAccess, share, ref secAttrs, mode, flagsAndAttributes, IntPtr.Zero); + fileHandle.IsAsync = _useAsyncIO; + + if (fileHandle.IsInvalid) + { + // Return a meaningful exception with the full path. + + // NT5 oddity - when trying to open "C:\" as a Win32FileStream, + // we usually get ERROR_PATH_NOT_FOUND from the OS. We should + // probably be consistent w/ every other directory. + int errorCode = Marshal.GetLastWin32Error(); + + if (errorCode == Interop.Errors.ERROR_PATH_NOT_FOUND && _path.Length == PathInternal.GetRootLength(_path)) + errorCode = Interop.Errors.ERROR_ACCESS_DENIED; + + throw Win32Marshal.GetExceptionForWin32Error(errorCode, _path); + } + + int fileType = Interop.Kernel32.GetFileType(fileHandle); + if (fileType != Interop.Kernel32.FileTypes.FILE_TYPE_DISK) + { + fileHandle.Dispose(); + throw new NotSupportedException(SR.NotSupported_FileStreamOnNonFiles); + } + + return fileHandle; + } + finally + { + Interop.Kernel32.SetErrorMode(oldMode); + } + } + } +} |