public DriveAccess(string Path) { if (Path == null || Path.Length == 0) throw new ArgumentNullException("Path"); driveHandle = CreateFile(Path, 0xC0000000, 0x03, IntPtr.Zero, 0x03, 0x80, IntPtr.Zero); if (driveHandle.IsInvalid) { driveHandle.Close(); driveHandle.Dispose(); driveHandle = null; throw new Exception("Win32 Exception : 0x" + Convert.ToString(Marshal.GetHRForLastWin32Error(), 16).PadLeft(8, '0')); } driveStream = new FileStream(driveHandle, FileAccess.ReadWrite); IntPtr p = Marshal.AllocHGlobal(24); uint returned; if (DeviceIoControl(driveHandle.DangerousGetHandle(), 0x00070000, IntPtr.Zero, 0, p, 40, out returned, IntPtr.Zero)) unsafe { driveGeometry = new DriveGeometry((byte*)p.ToPointer()); } else { Marshal.FreeHGlobal(p); throw new Exception("Could not get the drive geometry information!"); } Marshal.FreeHGlobal(p); }
/// <summary>Starts a new watch operation if one is not currently running.</summary> private void StartRaisingEvents() { // If we already have a cancellation object, we're already running. if (_cancellation != null) { return; } // Open an inotify file descriptor. Ideally this would be a constrained execution region, but we don't have access to // PrepareConstrainedRegions. We still use a finally block to house the code that opens the handle and stores it in // hopes of making it as non-interruptable as possible. Ideally the SafeFileHandle would be allocated before the block, // but SetHandle is protected and SafeFileHandle is sealed, so we're stuck doing the allocation here. SafeFileHandle handle; try { } finally { int fd; Interop.CheckIo(fd = Interop.libc.inotify_init()); handle = new SafeFileHandle((IntPtr)fd, ownsHandle: true); } try { // Create the cancellation object that will be used by this FileSystemWatcher to cancel the new watch operation CancellationTokenSource cancellation = new CancellationTokenSource(); // Start running. All state associated with the watch operation is stored in a separate object; this is done // to avoid race conditions that could result if the users quickly starts/stops/starts/stops/etc. causing multiple // active operations to all be outstanding at the same time. new RunningInstance( this, handle, _directory, IncludeSubdirectories, TranslateFilters(NotifyFilter), cancellation.Token); // Now that we've started running successfully, store the cancellation object and mark the instance // as running. We wait to store the cancellation token so that if there was a failure, StartRaisingEvents // may be called to try again without first having to call StopRaisingEvents. _cancellation = cancellation; _enabled = true; } catch { // If we fail to actually start the watching even though we've opened the // inotify handle, close the inotify handle proactively rather than waiting for it // to be finalized. handle.Dispose(); throw; } }
/// <summary>Initializes a stream for reading or writing a Unix file.</summary> /// <param name="path">The path to the file.</param> /// <param name="mode">How the file should be opened.</param> /// <param name="access">Whether the file will be read, written, or both.</param> /// <param name="share">What other access to the file should be allowed. This is currently ignored.</param> /// <param name="bufferSize">The size of the buffer to use when buffering.</param> /// <param name="options">Additional options for working with the file.</param> internal UnixFileStream(String path, FileMode mode, FileAccess access, FileShare share, int bufferSize, FileOptions options, FileStream parent) : base(parent) { // FileStream performs most of the general argument validation. We can assume here that the arguments // are all checked and consistent (e.g. non-null-or-empty path; valid enums in mode, access, share, and options; etc.) // Store the arguments _path = path; _access = access; _mode = mode; _options = options; _bufferLength = bufferSize; _useAsyncIO = (options & FileOptions.Asynchronous) != 0; // Translate the arguments into arguments for an open call Interop.Sys.OpenFlags openFlags = PreOpenConfigurationFromOptions(mode, access, options); // FileShare currently ignored Interop.Sys.Permissions openPermissions = Interop.Sys.Permissions.S_IRWXU; // creator has read/write/execute permissions; no permissions for anyone else // Open the file and store the safe handle. Subsequent code in this method expects the safe handle to be initialized. _fileHandle = SafeFileHandle.Open(path, openFlags, (int)openPermissions); _fileHandle.IsAsync = _useAsyncIO; // Lock the file if requested via FileShare. This is only advisory locking. FileShare.None implies an exclusive // lock on the file and all other modes use a shared lock. While this is not as granular as Windows, not mandatory, // and not atomic with file opening, it's better than nothing. try { Interop.Sys.LockOperations lockOperation = (share == FileShare.None) ? Interop.Sys.LockOperations.LOCK_EX : Interop.Sys.LockOperations.LOCK_SH; SysCall <Interop.Sys.LockOperations, int>((fd, op, _) => Interop.Sys.FLock(fd, op), lockOperation | Interop.Sys.LockOperations.LOCK_NB); } catch { _fileHandle.Dispose(); throw; } // Perform additional configurations on the stream based on the provided FileOptions PostOpenConfigureStreamFromOptions(); // Jump to the end of the file if opened as Append. if (_mode == FileMode.Append) { _appendStart = SeekCore(0, SeekOrigin.End); } }
private static async Task <byte[]> InternalReadAllBytesUnknownLengthAsync(SafeFileHandle sfh, CancellationToken cancellationToken) { byte[] rentedArray = ArrayPool <byte> .Shared.Rent(512); try { int bytesRead = 0; while (true) { if (bytesRead == rentedArray.Length) { uint newLength = (uint)rentedArray.Length * 2; if (newLength > Array.MaxLength) { newLength = (uint)Math.Max(Array.MaxLength, rentedArray.Length + 1); } byte[] tmp = ArrayPool <byte> .Shared.Rent((int)newLength); Buffer.BlockCopy(rentedArray, 0, tmp, 0, bytesRead); byte[] toReturn = rentedArray; rentedArray = tmp; ArrayPool <byte> .Shared.Return(toReturn); } Debug.Assert(bytesRead < rentedArray.Length); int n = await RandomAccess.ReadAtOffsetAsync(sfh, rentedArray.AsMemory(bytesRead), bytesRead, cancellationToken).ConfigureAwait(false); if (n == 0) { return(rentedArray.AsSpan(0, bytesRead).ToArray()); } bytesRead += n; } } finally { sfh.Dispose(); ArrayPool <byte> .Shared.Return(rentedArray); } }
protected override void Dispose(bool disposing) { // Nothing will be done differently based on whether we are // disposing vs. finalizing. This is taking advantage of the // weak ordering between normal finalizable objects & critical // finalizable objects, which I included in the SafeHandle // design for FileStream, which would often "just work" when // finalized. try { if (_handle != null && !_handle.IsClosed) { // Flush data to disk iff we were writing. After // thinking about this, we also don't need to flush // our read position, regardless of whether the handle // was exposed to the user. They probably would NOT // want us to do this. if (_writePos > 0) { FlushWrite(!disposing); } } } finally { if (_handle != null && !_handle.IsClosed) { _handle.Dispose(); } _canRead = false; _canWrite = false; _canSeek = false; // Don't set the buffer to null, to avoid a NullReferenceException // when users have a race condition in their code (ie, they call // Close when calling another method on Stream like Read). //_buffer = null; base.Dispose(disposing); } }
internal WindowsFileStreamStrategy(string path, FileMode mode, FileAccess access, FileShare share, FileOptions options) { string fullPath = Path.GetFullPath(path); _path = fullPath; _access = access; _fileHandle = FileStreamHelpers.OpenHandle(fullPath, mode, access, share, options); try { _canSeek = true; Init(mode, path); } catch { // If anything goes wrong while setting up the stream, make sure we deterministically dispose // of the opened handle. _fileHandle.Dispose(); _fileHandle = null !; throw; } }
/// <summary>Initializes a stream for reading or writing a Unix file.</summary> /// <param name="path">The path to the file.</param> /// <param name="mode">How the file should be opened.</param> /// <param name="access">Whether the file will be read, written, or both.</param> /// <param name="share">What other access to the file should be allowed. This is currently ignored.</param> /// <param name="bufferSize">The size of the buffer to use when buffering.</param> /// <param name="options">Additional options for working with the file.</param> internal UnixFileStream(String path, FileMode mode, FileAccess access, FileShare share, int bufferSize, FileOptions options, FileStream parent) : base(parent) { // FileStream performs most of the general argument validation. We can assume here that the arguments // are all checked and consistent (e.g. non-null-or-empty path; valid enums in mode, access, share, and options; etc.) // Store the arguments _path = path; _access = access; _mode = mode; _options = options; _bufferLength = bufferSize; if ((options & FileOptions.Asynchronous) != 0) { _useAsyncIO = true; _asyncState = new AsyncState(); } // Translate the arguments into arguments for an open call. Interop.Sys.OpenFlags openFlags = PreOpenConfigurationFromOptions(mode, access, options); // FileShare currently ignored // If the file gets created a new, we'll select the permissions for it. Most utilities by default use 666 (read and // write for all). However, on Windows it's possible to write out a file and then execute it. To maintain that similarity, // we use 766, so that in addition the user has execute privileges. No matter what we choose, it'll be subject to the umask // applied by the system, such that the actual permissions will typically be less than what we select here. const Interop.Sys.Permissions openPermissions = Interop.Sys.Permissions.S_IRWXU | Interop.Sys.Permissions.S_IRGRP | Interop.Sys.Permissions.S_IWGRP | Interop.Sys.Permissions.S_IROTH | Interop.Sys.Permissions.S_IWOTH; // Open the file and store the safe handle. Subsequent code in this method expects the safe handle to be initialized. _fileHandle = SafeFileHandle.Open(path, openFlags, (int)openPermissions); try { _fileHandle.IsAsync = _useAsyncIO; // Lock the file if requested via FileShare. This is only advisory locking. FileShare.None implies an exclusive // lock on the file and all other modes use a shared lock. While this is not as granular as Windows, not mandatory, // and not atomic with file opening, it's better than nothing. Some kinds of files, e.g. FIFOs, don't support // locking on some platforms, e.g. OSX, and so if flock returns ENOTSUP, we similarly treat it as a hint and ignore it, // as we don't want to entirely prevent usage of a particular file simply because locking isn't supported. Interop.Sys.LockOperations lockOperation = (share == FileShare.None) ? Interop.Sys.LockOperations.LOCK_EX : Interop.Sys.LockOperations.LOCK_SH; CheckFileCall(Interop.Sys.FLock(_fileHandle, lockOperation | Interop.Sys.LockOperations.LOCK_NB), ignoreNotSupported: true); // These provide hints around how the file will be accessed. Specifying both RandomAccess // and Sequential together doesn't make sense as they are two competing options on the same spectrum, // so if both are specified, we prefer RandomAccess (behavior on Windows is unspecified if both are provided). Interop.Sys.FileAdvice fadv = (_options & FileOptions.RandomAccess) != 0 ? Interop.Sys.FileAdvice.POSIX_FADV_RANDOM : (_options & FileOptions.SequentialScan) != 0 ? Interop.Sys.FileAdvice.POSIX_FADV_SEQUENTIAL : 0; if (fadv != 0) { CheckFileCall(Interop.Sys.PosixFAdvise(_fileHandle, 0, 0, fadv), ignoreNotSupported: true); // just a hint. } // Jump to the end of the file if opened as Append. if (_mode == FileMode.Append) { _appendStart = SeekCore(0, SeekOrigin.End); } } catch { // If anything goes wrong while setting up the stream, make sure we deterministically dispose // of the opened handle. _fileHandle.Dispose(); _fileHandle = null; throw; } }
public FileStream(string path, FileMode mode, FileAccess access, FileShare share, int bufferSize, FileOptions options) { if (path == null) { throw new ArgumentNullException(nameof(path), SR.ArgumentNull_Path); } if (path.Length == 0) { throw new ArgumentException(SR.Argument_EmptyPath, nameof(path)); } // don't include inheritable in our bounds check for share FileShare tempshare = share & ~FileShare.Inheritable; string? badArg = null; if (mode < FileMode.CreateNew || mode > FileMode.Append) { badArg = nameof(mode); } else if (access < FileAccess.Read || access > FileAccess.ReadWrite) { badArg = nameof(access); } else if (tempshare < FileShare.None || tempshare > (FileShare.ReadWrite | FileShare.Delete)) { badArg = nameof(share); } if (badArg != null) { throw new ArgumentOutOfRangeException(badArg, SR.ArgumentOutOfRange_Enum); } // NOTE: any change to FileOptions enum needs to be matched here in the error validation if (options != FileOptions.None && (options & ~(FileOptions.WriteThrough | FileOptions.Asynchronous | FileOptions.RandomAccess | FileOptions.DeleteOnClose | FileOptions.SequentialScan | FileOptions.Encrypted | (FileOptions)0x20000000 /* NoBuffering */)) != 0) { throw new ArgumentOutOfRangeException(nameof(options), SR.ArgumentOutOfRange_Enum); } if (bufferSize <= 0) { throw new ArgumentOutOfRangeException(nameof(bufferSize), SR.ArgumentOutOfRange_NeedPosNum); } // Write access validation if ((access & FileAccess.Write) == 0) { if (mode == FileMode.Truncate || mode == FileMode.CreateNew || mode == FileMode.Create || mode == FileMode.Append) { // No write access, mode and access disagree but flag access since mode comes first throw new ArgumentException(SR.Format(SR.Argument_InvalidFileModeAndAccessCombo, mode, access), nameof(access)); } } if ((access & FileAccess.Read) != 0 && mode == FileMode.Append) { throw new ArgumentException(SR.Argument_InvalidAppendMode, nameof(access)); } string fullPath = Path.GetFullPath(path); _path = fullPath; _access = access; _bufferLength = bufferSize; if ((options & FileOptions.Asynchronous) != 0) { _useAsyncIO = true; } if ((access & FileAccess.Write) == FileAccess.Write) { SerializationInfo.ThrowIfDeserializationInProgress("AllowFileWrites", ref s_cachedSerializationSwitch); } _fileHandle = OpenHandle(mode, share, options); try { Init(mode, share, path); } catch { // If anything goes wrong while setting up the stream, make sure we deterministically dispose // of the opened handle. _fileHandle.Dispose(); _fileHandle = null !; throw; } }
public FileStream(string path, FileMode mode, FileAccess access, FileShare share, int bufferSize, FileOptions options) { if (path == null) throw new ArgumentNullException(nameof(path), SR.ArgumentNull_Path); if (path.Length == 0) throw new ArgumentException(SR.Argument_EmptyPath, nameof(path)); // don't include inheritable in our bounds check for share FileShare tempshare = share & ~FileShare.Inheritable; string badArg = null; if (mode < FileMode.CreateNew || mode > FileMode.Append) badArg = "mode"; else if (access < FileAccess.Read || access > FileAccess.ReadWrite) badArg = "access"; else if (tempshare < FileShare.None || tempshare > (FileShare.ReadWrite | FileShare.Delete)) badArg = "share"; if (badArg != null) throw new ArgumentOutOfRangeException(badArg, SR.ArgumentOutOfRange_Enum); // NOTE: any change to FileOptions enum needs to be matched here in the error validation if (options != FileOptions.None && (options & ~(FileOptions.WriteThrough | FileOptions.Asynchronous | FileOptions.RandomAccess | FileOptions.DeleteOnClose | FileOptions.SequentialScan | FileOptions.Encrypted | (FileOptions)0x20000000 /* NoBuffering */)) != 0) throw new ArgumentOutOfRangeException(nameof(options), SR.ArgumentOutOfRange_Enum); if (bufferSize <= 0) throw new ArgumentOutOfRangeException(nameof(bufferSize), SR.ArgumentOutOfRange_NeedPosNum); // Write access validation if ((access & FileAccess.Write) == 0) { if (mode == FileMode.Truncate || mode == FileMode.CreateNew || mode == FileMode.Create || mode == FileMode.Append) { // No write access, mode and access disagree but flag access since mode comes first throw new ArgumentException(SR.Format(SR.Argument_InvalidFileModeAndAccessCombo, mode, access), nameof(access)); } } if ((access & FileAccess.Read) != 0 && mode == FileMode.Append) throw new ArgumentException(SR.Argument_InvalidAppendMode, nameof(access)); string fullPath = Path.GetFullPath(path); _path = fullPath; _access = access; _bufferLength = bufferSize; if ((options & FileOptions.Asynchronous) != 0) _useAsyncIO = true; _fileHandle = OpenHandle(mode, share, options); try { Init(mode, share); } catch { // If anything goes wrong while setting up the stream, make sure we deterministically dispose // of the opened handle. _fileHandle.Dispose(); _fileHandle = null; throw; } }
private void EnforceRetentionPolicy(SafeFileHandle handle, long lastPos) { switch (this._retention) { case LogRetentionOption.UnlimitedSequentialFiles: case LogRetentionOption.LimitedCircularFiles: case LogRetentionOption.LimitedSequentialFiles: if ((lastPos < this._maxFileSize) || (handle != this._handle)) { return; } lock (this.m_lockObject) { if ((handle == this._handle) && (lastPos >= this._maxFileSize)) { this._currentFileNum++; if ((this._retention == LogRetentionOption.LimitedCircularFiles) && (this._currentFileNum > this._maxNumberOfFiles)) { this._currentFileNum = 1; } else if ((this._retention == LogRetentionOption.LimitedSequentialFiles) && (this._currentFileNum > this._maxNumberOfFiles)) { this._DisableLogging(); return; } if (this._fileNameWithoutExt == null) { this._fileNameWithoutExt = Path.Combine(Path.GetDirectoryName(this._pathSav), Path.GetFileNameWithoutExtension(this._pathSav)); this._fileExt = Path.GetExtension(this._pathSav); } string path = (this._currentFileNum == 1) ? this._pathSav : (this._fileNameWithoutExt + this._currentFileNum.ToString(CultureInfo.InvariantCulture) + this._fileExt); try { this._Init(path, this._fAccessSav, this._shareSav, this._secAttrsSav, this._secAccessSav, this._modeSav, this._flagsAndAttributesSav, this._seekToEndSav); if ((handle != null) && !handle.IsClosed) { handle.Dispose(); } } catch (IOException) { this._handle = handle; this._retentionRetryCount++; if (this._retentionRetryCount >= 2) { this._DisableLogging(); } } catch (UnauthorizedAccessException) { this._DisableLogging(); } catch (Exception) { this._DisableLogging(); } } return; } break; case LogRetentionOption.SingleFileUnboundedSize: return; case LogRetentionOption.SingleFileBoundedSize: break; default: return; } if (lastPos >= this._maxFileSize) { this._DisableLogging(); } }
/// <summary>Initializes a stream for reading or writing a Unix file.</summary> /// <param name="path">The path to the file.</param> /// <param name="mode">How the file should be opened.</param> /// <param name="access">Whether the file will be read, written, or both.</param> /// <param name="share">What other access to the file should be allowed. This is currently ignored.</param> /// <param name="bufferSize">The size of the buffer to use when buffering.</param> /// <param name="options">Additional options for working with the file.</param> internal UnixFileStream(String path, FileMode mode, FileAccess access, FileShare share, int bufferSize, FileOptions options, FileStream parent) : base(parent) { // FileStream performs most of the general argument validation. We can assume here that the arguments // are all checked and consistent (e.g. non-null-or-empty path; valid enums in mode, access, share, and options; etc.) // Store the arguments _path = path; _access = access; _mode = mode; _options = options; _bufferLength = bufferSize; if ((options & FileOptions.Asynchronous) != 0) { _useAsyncIO = true; _asyncState = new AsyncState(); } // Translate the arguments into arguments for an open call Interop.Sys.OpenFlags openFlags = PreOpenConfigurationFromOptions(mode, access, options); // FileShare currently ignored Interop.Sys.Permissions openPermissions = Interop.Sys.Permissions.S_IRWXU; // creator has read/write/execute permissions; no permissions for anyone else // Open the file and store the safe handle. Subsequent code in this method expects the safe handle to be initialized. _fileHandle = SafeFileHandle.Open(path, openFlags, (int)openPermissions); try { _fileHandle.IsAsync = _useAsyncIO; // Lock the file if requested via FileShare. This is only advisory locking. FileShare.None implies an exclusive // lock on the file and all other modes use a shared lock. While this is not as granular as Windows, not mandatory, // and not atomic with file opening, it's better than nothing. Interop.Sys.LockOperations lockOperation = (share == FileShare.None) ? Interop.Sys.LockOperations.LOCK_EX : Interop.Sys.LockOperations.LOCK_SH; CheckFileCall(Interop.Sys.FLock(_fileHandle, lockOperation | Interop.Sys.LockOperations.LOCK_NB)); // These provide hints around how the file will be accessed. Specifying both RandomAccess // and Sequential together doesn't make sense as they are two competing options on the same spectrum, // so if both are specified, we prefer RandomAccess (behavior on Windows is unspecified if both are provided). Interop.Sys.FileAdvice fadv = (_options & FileOptions.RandomAccess) != 0 ? Interop.Sys.FileAdvice.POSIX_FADV_RANDOM : (_options & FileOptions.SequentialScan) != 0 ? Interop.Sys.FileAdvice.POSIX_FADV_SEQUENTIAL : 0; if (fadv != 0) { CheckFileCall(Interop.Sys.PosixFAdvise(_fileHandle, 0, 0, fadv), ignoreNotSupported: true); // just a hint. } // Jump to the end of the file if opened as Append. if (_mode == FileMode.Append) { _appendStart = SeekCore(0, SeekOrigin.End); } } catch { // If anything goes wrong while setting up the stream, make sure we deterministically dispose // of the opened handle. _fileHandle.Dispose(); _fileHandle = null; throw; } }
private void EnforceRetentionPolicy(SafeFileHandle handle, long lastPos) { switch (_retention) { case LogRetentionOption.LimitedSequentialFiles: case LogRetentionOption.UnlimitedSequentialFiles: case LogRetentionOption.LimitedCircularFiles: if ((lastPos >= _maxFileSize) && (handle == _handle)){ lock (m_lockObject) { if ((handle != _handle) || (lastPos < _maxFileSize)) return; _currentFileNum++; if ((_retention == LogRetentionOption.LimitedCircularFiles) && (_currentFileNum > _maxNumberOfFiles)) { _currentFileNum = 1; } else if ((_retention == LogRetentionOption.LimitedSequentialFiles) && (_currentFileNum > _maxNumberOfFiles)) { _DisableLogging(); return; } if (_fileNameWithoutExt == null) { _fileNameWithoutExt = Path.Combine(Path.GetDirectoryName(_pathSav), Path.GetFileNameWithoutExtension(_pathSav)); _fileExt = Path.GetExtension(_pathSav); } string path = (_currentFileNum == 1)?_pathSav: _fileNameWithoutExt + _currentFileNum.ToString(CultureInfo.InvariantCulture) + _fileExt; try { _Init(path, _fAccessSav, _shareSav, _secAttrsSav, _secAccessSav, _modeSav, _flagsAndAttributesSav, _seekToEndSav); // Dispose the old handle and release the file write lock // No need to flush the buffer as we just came off a write if (handle != null && !handle.IsClosed) { handle.Dispose(); } } catch (IOException ) { // Should we do this only for ERROR_SHARING_VIOLATION? //if (UnsafeNativeMethods.MakeErrorCodeFromHR(Marshal.GetHRForException(ioexc)) != InternalResources.ERROR_SHARING_VIOLATION) break; // Possible sharing violation - ----? Let the next iteration try again // For now revert the handle to the original one _handle = handle; _retentionRetryCount++; if (_retentionRetryCount >= _retentionRetryThreshold) { _DisableLogging(); } #if DEBUG throw; #endif } catch (UnauthorizedAccessException ) { // Indicative of ACL issues _DisableLogging(); #if DEBUG throw; #endif } catch (Exception ) { _DisableLogging(); #if DEBUG throw; #endif } } } break; case LogRetentionOption.SingleFileBoundedSize: if (lastPos >= _maxFileSize) _DisableLogging(); break; case LogRetentionOption.SingleFileUnboundedSize: break; } }
private void Init(String path, FileMode mode, FileAccess access, FileShare share, int bufferSize, FileOptions options, Interop.mincore.SECURITY_ATTRIBUTES secAttrs) { _exposedHandle = false; int fAccess = ((access & FileAccess.Read) == FileAccess.Read ? GENERIC_READ : 0) | ((access & FileAccess.Write) == FileAccess.Write ? GENERIC_WRITE : 0); _fileName = path; // 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; bool seekToEnd = (mode == FileMode.Append); // Must use a valid Win32 constant here... if (mode == FileMode.Append) mode = FileMode.OpenOrCreate; if ((options & FileOptions.Asynchronous) != 0) _isAsync = true; 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.mincore.SecurityOptions.SECURITY_SQOS_PRESENT | Interop.mincore.SecurityOptions.SECURITY_ANONYMOUS); // Don't pop up a dialog for reading from an empty floppy drive uint oldMode = Interop.mincore.SetErrorMode(Interop.mincore.SEM_FAILCRITICALERRORS); try { _handle = Interop.mincore.SafeCreateFile(path, fAccess, share, ref secAttrs, mode, flagsAndAttributes, IntPtr.Zero); _handle.IsAsync = _isAsync; if (_handle.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.mincore.Errors.ERROR_PATH_NOT_FOUND && path.Equals(Directory.InternalGetDirectoryRoot(path))) errorCode = Interop.mincore.Errors.ERROR_ACCESS_DENIED; throw Win32Marshal.GetExceptionForWin32Error(errorCode, _fileName); } } finally { Interop.mincore.SetErrorMode(oldMode); } // Disallow access to all non-file devices from the Win32FileStream // constructors that take a String. Everyone else can call // CreateFile themselves then use the constructor that takes an // IntPtr. Disallows "con:", "com1:", "lpt1:", etc. int fileType = Interop.mincore.GetFileType(_handle); if (fileType != Interop.mincore.FileTypes.FILE_TYPE_DISK) { _handle.Dispose(); throw new NotSupportedException(SR.NotSupported_FileStreamOnNonFiles); } // This is necessary for async IO using IO Completion ports via our // managed Threadpool API's. This (theoretically) calls the OS's // BindIoCompletionCallback method, and passes in a stub for the // LPOVERLAPPED_COMPLETION_ROUTINE. This stub looks at the Overlapped // struct for this request and gets a delegate to a managed callback // from there, which it then calls on a threadpool thread. (We allocate // our native OVERLAPPED structs 2 pointers too large and store EE state // & GC handles there, one to an IAsyncResult, the other to a delegate.) if (_isAsync) { try { _handle.ThreadPoolBinding = ThreadPoolBoundHandle.BindHandle(_handle); } catch (ArgumentException ex) { throw new IOException(SR.IO_BindHandleFailed, ex); } finally { if (_handle.ThreadPoolBinding == null) { // We should close the handle so that the handle is not open until SafeFileHandle GC Debug.Assert(!_exposedHandle, "Are we closing handle that we exposed/not own, how?"); _handle.Dispose(); } } } _canRead = (access & FileAccess.Read) != 0; _canWrite = (access & FileAccess.Write) != 0; _canSeek = true; _isPipe = false; _pos = 0; _bufferSize = bufferSize; _readPos = 0; _readLen = 0; _writePos = 0; // For Append mode... if (seekToEnd) { _appendStart = SeekCore(0, SeekOrigin.End); } else { _appendStart = -1; } }
private void EnforceRetentionPolicy(SafeFileHandle handle, long lastPos) { switch (_retention) { case LogRetentionOption.LimitedSequentialFiles: case LogRetentionOption.UnlimitedSequentialFiles: case LogRetentionOption.LimitedCircularFiles: if ((lastPos >= _maxFileSize) && (handle == _handle)) { lock (m_lockObject) { if ((handle != _handle) || (lastPos < _maxFileSize)) { return; } _currentFileNum++; if ((_retention == LogRetentionOption.LimitedCircularFiles) && (_currentFileNum > _maxNumberOfFiles)) { _currentFileNum = 1; } else if ((_retention == LogRetentionOption.LimitedSequentialFiles) && (_currentFileNum > _maxNumberOfFiles)) { _DisableLogging(); return; } if (_fileNameWithoutExt == null) { _fileNameWithoutExt = Path.Combine(Path.GetDirectoryName(_pathSav), Path.GetFileNameWithoutExtension(_pathSav)); _fileExt = Path.GetExtension(_pathSav); } string path = (_currentFileNum == 1)?_pathSav: _fileNameWithoutExt + _currentFileNum.ToString(CultureInfo.InvariantCulture) + _fileExt; try { _Init(path, _fAccessSav, _shareSav, _secAttrsSav, _secAccessSav, _modeSav, _flagsAndAttributesSav, _seekToEndSav); // Dispose the old handle and release the file write lock // No need to flush the buffer as we just came off a write if (handle != null && !handle.IsClosed) { handle.Dispose(); } } catch (IOException) { // Should we do this only for ERROR_SHARING_VIOLATION? //if (UnsafeNativeMethods.MakeErrorCodeFromHR(Marshal.GetHRForException(ioexc)) != InternalResources.ERROR_SHARING_VIOLATION) break; // Possible sharing violation - ----? Let the next iteration try again // For now revert the handle to the original one _handle = handle; _retentionRetryCount++; if (_retentionRetryCount >= _retentionRetryThreshold) { _DisableLogging(); } #if DEBUG throw; #endif } catch (UnauthorizedAccessException) { // Indicative of ACL issues _DisableLogging(); #if DEBUG throw; #endif } catch (Exception) { _DisableLogging(); #if DEBUG throw; #endif } } } break; case LogRetentionOption.SingleFileBoundedSize: if (lastPos >= _maxFileSize) { _DisableLogging(); } break; case LogRetentionOption.SingleFileUnboundedSize: break; } }
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); } }
/// <summary> /// Opens a reparse point. /// </summary> /// <param name="reparsePoint">The reparse point to open.</param> /// <param name="accessMode">Access mode use to open the reparse point.</param> /// <returns>A safe file handle.</returns> private static SafeFileHandle OpenReparsePoint(string reparsePoint, EFileAccess accessMode) { SafeFileHandle reparsePointHandle = null; try { IntPtr createFileResult = CreateFile( reparsePoint, accessMode, EFileShare.Read | EFileShare.Write | EFileShare.Delete, IntPtr.Zero, ECreationDisposition.OpenExisting, EFileAttributes.BackupSemantics | EFileAttributes.OpenReparsePoint, IntPtr.Zero); if (Marshal.GetLastWin32Error() != 0) { ThrowLastWin32Error(Strings.UnableToOpenReparsePoint); } reparsePointHandle = new SafeFileHandle(createFileResult, true); return reparsePointHandle; } catch { if (reparsePointHandle != null) { reparsePointHandle.Dispose(); } throw; } }