Code:
/ 4.0 / 4.0 / DEVDIV_TFS / Dev10 / Releases / RTMRel / ndp / fx / src / Core / System / IO / LogStream.cs / 1305376 / LogStream.cs
// ==++==
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
// ==--==
/*============================================================
**
** Class: LogStream
**
===========================================================*/
using System;
using Microsoft.Win32;
using Microsoft.Win32.SafeHandles;
using System.Security;
using System.Security.Permissions;
using System.Threading;
using System.Runtime.InteropServices;
using System.Runtime.Remoting.Messaging;
using System.Runtime.CompilerServices;
using System.Globalization;
using System.Runtime.Versioning;
using System.Diagnostics;
using System.Diagnostics.Contracts;
namespace System.IO {
// This stream has very limited support to enable EventSchemaTraceListener
// Eventually we might want to add more functionality and expose this type
internal class LogStream : BufferedStream2
{
internal const long DefaultFileSize = 10*1000*1024;
internal const int DefaultNumberOfFiles = 2;
internal const LogRetentionOption DefaultRetention = LogRetentionOption.SingleFileUnboundedSize;
// Retention policy
private const int _retentionRetryThreshold = 2;
private LogRetentionOption _retention;
private long _maxFileSize = DefaultFileSize;
private int _maxNumberOfFiles = DefaultNumberOfFiles;
private int _currentFileNum = 1;
bool _disableLogging;
int _retentionRetryCount;
private bool _canRead;
private bool _canWrite;
private bool _canSeek;
private SafeFileHandle _handle;
private String _fileName; // Fully qualified file name.
string _fileNameWithoutExt;
string _fileExt;
// Save input for retention
string _pathSav;
int _fAccessSav;
FileShare _shareSav;
UnsafeNativeMethods.SECURITY_ATTRIBUTES _secAttrsSav;
FileIOPermissionAccess _secAccessSav;
FileMode _modeSav;
int _flagsAndAttributesSav;
bool _seekToEndSav;
private readonly object m_lockObject = new Object();
//Limited to immediate internal need from EventSchemaTraceListener
//Not param validation done!!
[ResourceExposure(ResourceScope.Machine)]
[ResourceConsumption(ResourceScope.Machine)]
//
//
//
//
[System.Security.SecurityCritical]
internal LogStream(String path, int bufferSize, LogRetentionOption retention, long maxFileSize, int maxNumOfFiles)
{
Debug.Assert(!String.IsNullOrEmpty(path));
// Get absolute path - Security needs this to prevent something
// like trying to create a file in c:\tmp with the name
// "..\WinNT\System32\ntoskrnl.exe". Store it for user convenience.
//String filePath = Path.GetFullPathInternal(path);
String filePath = Path.GetFullPath(path);
_fileName = filePath;
// Prevent access to your disk drives as raw block devices.
if (filePath.StartsWith("\\\\.\\", StringComparison.Ordinal))
throw new NotSupportedException(SR.GetString(SR.NotSupported_IONonFileDevices));
UnsafeNativeMethods.SECURITY_ATTRIBUTES secAttrs = GetSecAttrs(FileShare.Read);
// 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
int flagsAndAttributes = (int)FileOptions.None | (UnsafeNativeMethods.SECURITY_SQOS_PRESENT | UnsafeNativeMethods.SECURITY_ANONYMOUS);
// Only write is enabled
//_canRead = false;
//_canSeek = false;
_canWrite = true;
_pathSav = filePath;
_fAccessSav = UnsafeNativeMethods.GENERIC_WRITE;
_shareSav = FileShare.Read;
_secAttrsSav = secAttrs;
_secAccessSav = FileIOPermissionAccess.Write;
_modeSav = (retention != LogRetentionOption.SingleFileUnboundedSize)? FileMode.Create : FileMode.OpenOrCreate;
_flagsAndAttributesSav = flagsAndAttributes;
_seekToEndSav = (retention != LogRetentionOption.SingleFileUnboundedSize)? false : true;
this.bufferSize = bufferSize;
_retention = retention;
_maxFileSize = maxFileSize;
_maxNumberOfFiles = maxNumOfFiles;
_Init(filePath, _fAccessSav, _shareSav, _secAttrsSav, _secAccessSav, _modeSav, _flagsAndAttributesSav, _seekToEndSav);
}
//
//
//
//
//
//
//
//
//
[System.Security.SecurityCritical]
internal void _Init(String path, int fAccess, FileShare share, UnsafeNativeMethods.SECURITY_ATTRIBUTES secAttrs, FileIOPermissionAccess secAccess,
FileMode mode, int flagsAndAttributes, bool seekToEnd)
{
String filePath = Path.GetFullPath(path);
_fileName = filePath;
new FileIOPermission(secAccess, new String[] { filePath }).Demand();
// Don't pop up a dialog for reading from an emtpy floppy drive
int oldMode = UnsafeNativeMethods.SetErrorMode(UnsafeNativeMethods.SEM_FAILCRITICALERRORS);
try {
_handle = UnsafeNativeMethods.SafeCreateFile(filePath, fAccess, share, secAttrs, mode, flagsAndAttributes, UnsafeNativeMethods.NULL);
int errorCode = Marshal.GetLastWin32Error();
if (_handle.IsInvalid) {
// Return a meaningful exception, using the RELATIVE path to
// the file to avoid returning extra information to the caller
// unless they have path discovery permission, in which case
// the full path is fine & useful.
// We need to give an exception, and preferably it would include
// the fully qualified path name. Do security check here. If
// we fail, give back the msgPath, which should not reveal much.
// While this logic is largely duplicated in
// __Error.WinIOError, we need this for
// IsolatedStorageLogFileStream.
bool canGiveFullPath = false;
try {
new FileIOPermission(FileIOPermissionAccess.PathDiscovery, new String[] { _fileName }).Demand();
canGiveFullPath = true;
}
catch(SecurityException) {}
if (canGiveFullPath)
__Error.WinIOError(errorCode, _fileName);
else
__Error.WinIOError(errorCode, Path.GetFileName(_fileName));
}
}
finally {
UnsafeNativeMethods.SetErrorMode(oldMode);
}
Debug.Assert(UnsafeNativeMethods.GetFileType(_handle) == UnsafeNativeMethods.FILE_TYPE_DISK, "did someone accidentally removed the device type check from SafeCreateFile P/Invoke wrapper?");
pos = 0;
// For Append mode...
if (seekToEnd) {
SeekCore(0, SeekOrigin.End);
}
}
public override bool CanRead {
[Pure]
get { return _canRead; }
}
public override bool CanWrite {
[Pure]
get { return _canWrite; }
}
public override bool CanSeek {
[Pure]
get { return _canSeek; }
}
public override long Length {
get {
throw new NotSupportedException();
}
}
public override long Position {
get {
throw new NotSupportedException();
}
set {
throw new NotSupportedException();
}
}
public override void SetLength(long value)
{
throw new NotSupportedException();
}
public override long Seek(long offset, SeekOrigin origin)
{
throw new NotSupportedException();
}
public override int Read(byte[] array, int offset, int count)
{
throw new NotSupportedException();
}
//
//
//
//
//
[System.Security.SecurityCritical]
protected override unsafe void WriteCore(byte[] buffer, int offset, int count, bool blockForWrite, out long streamPos) {
Debug.Assert(CanWrite, "CanWrite");
Debug.Assert(buffer != null, "buffer != null");
Debug.Assert(offset >= 0, "offset is negative");
Debug.Assert(count >= 0, "count is negative");
int hr = 0;
int r = WriteFileNative(buffer, offset, count, null, out hr);
if (r == -1) {
// For pipes, ERROR_NO_DATA is not an error, but the pipe is closing.
if (hr == UnsafeNativeMethods.ERROR_NO_DATA) {
r = 0;
}
else {
// ERROR_INVALID_PARAMETER may be returned for writes
// where the position is too large (ie, writing at Int64.MaxValue
// on Win9x) OR for synchronous writes to a handle opened
// asynchronously.
if (hr == UnsafeNativeMethods.ERROR_INVALID_PARAMETER)
throw new IOException(SR.GetString(SR.IO_FileTooLongOrHandleNotSync));
__Error.WinIOError(hr, String.Empty);
}
}
Debug.Assert(r >= 0, "WriteCore is likely broken.");
// update cached position
streamPos = AddUnderlyingStreamPosition((long)r);
EnforceRetentionPolicy(_handle, streamPos);
streamPos = pos;
return;
}
//
//
//
//
//
//
//
//
[System.Security.SecurityCritical]
unsafe private int WriteFileNative(byte[] bytes, int offset, int count, NativeOverlapped* overlapped, out int hr) {
if (_handle.IsClosed) __Error.FileNotOpen();
if (_disableLogging) {
hr = 0;
return 0;
}
Debug.Assert(offset >= 0, "offset >= 0");
Debug.Assert(count >= 0, "count >= 0");
Debug.Assert(bytes != null, "bytes != null");
// Don't corrupt memory when multiple threads are erroneously writing
// to this stream simultaneously. (the OS is reading from
// the array we pass to WriteFile, but if we read beyond the end and
// that memory isn't allocated, we could get an AV.)
if (bytes.Length - offset < count)
throw new IndexOutOfRangeException(SR.GetString(SR.IndexOutOfRange_IORaceCondition));
// You can't use the fixed statement on an array of length 0.
if (bytes.Length==0) {
hr = 0;
return 0;
}
int numBytesWritten = 0;
int r = 0;
fixed(byte* p = bytes) {
r = UnsafeNativeMethods.WriteFile(_handle, p + offset, count, out numBytesWritten, overlapped);
}
if (r == 0) {
// We should never silently ---- an error here without some
// extra work. We must make sure that BeginWriteCore won't return an
// IAsyncResult that will cause EndWrite to block, since the OS won't
// call AsyncFSCallback for us.
hr = Marshal.GetLastWin32Error();
// For invalid handles, detect the error and mark our handle
// as closed to give slightly better error messages. Also
// help ensure we avoid handle recycling bugs.
if (hr == UnsafeNativeMethods.ERROR_INVALID_HANDLE)
_handle.SetHandleAsInvalid();
return -1;
}
else
hr = 0;
return numBytesWritten;
}
// This doesn't do argument checking. Necessary for SetLength, which must
// set the file pointer beyond the end of the file. This will update the
// internal position
//
//
//
//
//
//
[System.Security.SecurityCritical]
private long SeekCore(long offset, SeekOrigin origin)
{
Debug.Assert(!_handle.IsClosed, "!_handle.IsClosed");
Debug.Assert(origin>=SeekOrigin.Begin && origin<=SeekOrigin.End, "origin>=SeekOrigin.Begin && origin<=SeekOrigin.End");
int hr = 0;
long ret = 0;
ret = UnsafeNativeMethods.SetFilePointer(_handle, offset, origin, out hr);
if (ret == -1) {
// For invalid handles, detect the error and mark our handle
// as closed to give slightly better error messages. Also
// help ensure we avoid handle recycling bugs.
if (hr == UnsafeNativeMethods.ERROR_INVALID_HANDLE)
_handle.SetHandleAsInvalid();
__Error.WinIOError(hr, String.Empty);
}
UnderlyingStreamPosition = ret;
return ret;
}
//
//
//
//
[System.Security.SecurityCritical]
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 LogStream, which would often "just work" when
// finalized.
try {
if (_handle == null || _handle.IsClosed) {
// Make sure BufferedStream doesn't try to flush data on a closed handle
DiscardBuffer();
}
}
finally {
try {
// Cleanup base streams
base.Dispose(disposing);
}
finally {
if (_handle != null && !_handle.IsClosed)
_handle.Dispose();
_handle = null;
_canRead = false;
_canWrite = false;
_canSeek = false;
}
}
}
//
//
//
[System.Security.SecurityCritical]
~LogStream()
{
if (_handle != null) {
Dispose(false);
}
}
//
//
//
//
//
[System.Security.SecurityCritical]
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;
}
}
// When we enable this class widely, we need to raise an
// event when we disable logging due to rention policy or
// error such as ACL that is preventing retention
[MethodImplAttribute(MethodImplOptions.Synchronized)]
private void _DisableLogging()
{
// Discard write buffer?
_disableLogging = true;
}
//
//
//
[System.Security.SecurityCritical]
private static UnsafeNativeMethods.SECURITY_ATTRIBUTES GetSecAttrs(FileShare share)
{
UnsafeNativeMethods.SECURITY_ATTRIBUTES secAttrs = null;
if ((share & FileShare.Inheritable) != 0) {
secAttrs = new UnsafeNativeMethods.SECURITY_ATTRIBUTES();
secAttrs.nLength = (int)Marshal.SizeOf(secAttrs);
secAttrs.bInheritHandle = 1;
}
return secAttrs;
}
}
}
// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
// ==++==
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
// ==--==
/*============================================================
**
** Class: LogStream
**
===========================================================*/
using System;
using Microsoft.Win32;
using Microsoft.Win32.SafeHandles;
using System.Security;
using System.Security.Permissions;
using System.Threading;
using System.Runtime.InteropServices;
using System.Runtime.Remoting.Messaging;
using System.Runtime.CompilerServices;
using System.Globalization;
using System.Runtime.Versioning;
using System.Diagnostics;
using System.Diagnostics.Contracts;
namespace System.IO {
// This stream has very limited support to enable EventSchemaTraceListener
// Eventually we might want to add more functionality and expose this type
internal class LogStream : BufferedStream2
{
internal const long DefaultFileSize = 10*1000*1024;
internal const int DefaultNumberOfFiles = 2;
internal const LogRetentionOption DefaultRetention = LogRetentionOption.SingleFileUnboundedSize;
// Retention policy
private const int _retentionRetryThreshold = 2;
private LogRetentionOption _retention;
private long _maxFileSize = DefaultFileSize;
private int _maxNumberOfFiles = DefaultNumberOfFiles;
private int _currentFileNum = 1;
bool _disableLogging;
int _retentionRetryCount;
private bool _canRead;
private bool _canWrite;
private bool _canSeek;
private SafeFileHandle _handle;
private String _fileName; // Fully qualified file name.
string _fileNameWithoutExt;
string _fileExt;
// Save input for retention
string _pathSav;
int _fAccessSav;
FileShare _shareSav;
UnsafeNativeMethods.SECURITY_ATTRIBUTES _secAttrsSav;
FileIOPermissionAccess _secAccessSav;
FileMode _modeSav;
int _flagsAndAttributesSav;
bool _seekToEndSav;
private readonly object m_lockObject = new Object();
//Limited to immediate internal need from EventSchemaTraceListener
//Not param validation done!!
[ResourceExposure(ResourceScope.Machine)]
[ResourceConsumption(ResourceScope.Machine)]
//
//
//
//
[System.Security.SecurityCritical]
internal LogStream(String path, int bufferSize, LogRetentionOption retention, long maxFileSize, int maxNumOfFiles)
{
Debug.Assert(!String.IsNullOrEmpty(path));
// Get absolute path - Security needs this to prevent something
// like trying to create a file in c:\tmp with the name
// "..\WinNT\System32\ntoskrnl.exe". Store it for user convenience.
//String filePath = Path.GetFullPathInternal(path);
String filePath = Path.GetFullPath(path);
_fileName = filePath;
// Prevent access to your disk drives as raw block devices.
if (filePath.StartsWith("\\\\.\\", StringComparison.Ordinal))
throw new NotSupportedException(SR.GetString(SR.NotSupported_IONonFileDevices));
UnsafeNativeMethods.SECURITY_ATTRIBUTES secAttrs = GetSecAttrs(FileShare.Read);
// 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
int flagsAndAttributes = (int)FileOptions.None | (UnsafeNativeMethods.SECURITY_SQOS_PRESENT | UnsafeNativeMethods.SECURITY_ANONYMOUS);
// Only write is enabled
//_canRead = false;
//_canSeek = false;
_canWrite = true;
_pathSav = filePath;
_fAccessSav = UnsafeNativeMethods.GENERIC_WRITE;
_shareSav = FileShare.Read;
_secAttrsSav = secAttrs;
_secAccessSav = FileIOPermissionAccess.Write;
_modeSav = (retention != LogRetentionOption.SingleFileUnboundedSize)? FileMode.Create : FileMode.OpenOrCreate;
_flagsAndAttributesSav = flagsAndAttributes;
_seekToEndSav = (retention != LogRetentionOption.SingleFileUnboundedSize)? false : true;
this.bufferSize = bufferSize;
_retention = retention;
_maxFileSize = maxFileSize;
_maxNumberOfFiles = maxNumOfFiles;
_Init(filePath, _fAccessSav, _shareSav, _secAttrsSav, _secAccessSav, _modeSav, _flagsAndAttributesSav, _seekToEndSav);
}
//
//
//
//
//
//
//
//
//
[System.Security.SecurityCritical]
internal void _Init(String path, int fAccess, FileShare share, UnsafeNativeMethods.SECURITY_ATTRIBUTES secAttrs, FileIOPermissionAccess secAccess,
FileMode mode, int flagsAndAttributes, bool seekToEnd)
{
String filePath = Path.GetFullPath(path);
_fileName = filePath;
new FileIOPermission(secAccess, new String[] { filePath }).Demand();
// Don't pop up a dialog for reading from an emtpy floppy drive
int oldMode = UnsafeNativeMethods.SetErrorMode(UnsafeNativeMethods.SEM_FAILCRITICALERRORS);
try {
_handle = UnsafeNativeMethods.SafeCreateFile(filePath, fAccess, share, secAttrs, mode, flagsAndAttributes, UnsafeNativeMethods.NULL);
int errorCode = Marshal.GetLastWin32Error();
if (_handle.IsInvalid) {
// Return a meaningful exception, using the RELATIVE path to
// the file to avoid returning extra information to the caller
// unless they have path discovery permission, in which case
// the full path is fine & useful.
// We need to give an exception, and preferably it would include
// the fully qualified path name. Do security check here. If
// we fail, give back the msgPath, which should not reveal much.
// While this logic is largely duplicated in
// __Error.WinIOError, we need this for
// IsolatedStorageLogFileStream.
bool canGiveFullPath = false;
try {
new FileIOPermission(FileIOPermissionAccess.PathDiscovery, new String[] { _fileName }).Demand();
canGiveFullPath = true;
}
catch(SecurityException) {}
if (canGiveFullPath)
__Error.WinIOError(errorCode, _fileName);
else
__Error.WinIOError(errorCode, Path.GetFileName(_fileName));
}
}
finally {
UnsafeNativeMethods.SetErrorMode(oldMode);
}
Debug.Assert(UnsafeNativeMethods.GetFileType(_handle) == UnsafeNativeMethods.FILE_TYPE_DISK, "did someone accidentally removed the device type check from SafeCreateFile P/Invoke wrapper?");
pos = 0;
// For Append mode...
if (seekToEnd) {
SeekCore(0, SeekOrigin.End);
}
}
public override bool CanRead {
[Pure]
get { return _canRead; }
}
public override bool CanWrite {
[Pure]
get { return _canWrite; }
}
public override bool CanSeek {
[Pure]
get { return _canSeek; }
}
public override long Length {
get {
throw new NotSupportedException();
}
}
public override long Position {
get {
throw new NotSupportedException();
}
set {
throw new NotSupportedException();
}
}
public override void SetLength(long value)
{
throw new NotSupportedException();
}
public override long Seek(long offset, SeekOrigin origin)
{
throw new NotSupportedException();
}
public override int Read(byte[] array, int offset, int count)
{
throw new NotSupportedException();
}
//
//
//
//
//
[System.Security.SecurityCritical]
protected override unsafe void WriteCore(byte[] buffer, int offset, int count, bool blockForWrite, out long streamPos) {
Debug.Assert(CanWrite, "CanWrite");
Debug.Assert(buffer != null, "buffer != null");
Debug.Assert(offset >= 0, "offset is negative");
Debug.Assert(count >= 0, "count is negative");
int hr = 0;
int r = WriteFileNative(buffer, offset, count, null, out hr);
if (r == -1) {
// For pipes, ERROR_NO_DATA is not an error, but the pipe is closing.
if (hr == UnsafeNativeMethods.ERROR_NO_DATA) {
r = 0;
}
else {
// ERROR_INVALID_PARAMETER may be returned for writes
// where the position is too large (ie, writing at Int64.MaxValue
// on Win9x) OR for synchronous writes to a handle opened
// asynchronously.
if (hr == UnsafeNativeMethods.ERROR_INVALID_PARAMETER)
throw new IOException(SR.GetString(SR.IO_FileTooLongOrHandleNotSync));
__Error.WinIOError(hr, String.Empty);
}
}
Debug.Assert(r >= 0, "WriteCore is likely broken.");
// update cached position
streamPos = AddUnderlyingStreamPosition((long)r);
EnforceRetentionPolicy(_handle, streamPos);
streamPos = pos;
return;
}
//
//
//
//
//
//
//
//
[System.Security.SecurityCritical]
unsafe private int WriteFileNative(byte[] bytes, int offset, int count, NativeOverlapped* overlapped, out int hr) {
if (_handle.IsClosed) __Error.FileNotOpen();
if (_disableLogging) {
hr = 0;
return 0;
}
Debug.Assert(offset >= 0, "offset >= 0");
Debug.Assert(count >= 0, "count >= 0");
Debug.Assert(bytes != null, "bytes != null");
// Don't corrupt memory when multiple threads are erroneously writing
// to this stream simultaneously. (the OS is reading from
// the array we pass to WriteFile, but if we read beyond the end and
// that memory isn't allocated, we could get an AV.)
if (bytes.Length - offset < count)
throw new IndexOutOfRangeException(SR.GetString(SR.IndexOutOfRange_IORaceCondition));
// You can't use the fixed statement on an array of length 0.
if (bytes.Length==0) {
hr = 0;
return 0;
}
int numBytesWritten = 0;
int r = 0;
fixed(byte* p = bytes) {
r = UnsafeNativeMethods.WriteFile(_handle, p + offset, count, out numBytesWritten, overlapped);
}
if (r == 0) {
// We should never silently ---- an error here without some
// extra work. We must make sure that BeginWriteCore won't return an
// IAsyncResult that will cause EndWrite to block, since the OS won't
// call AsyncFSCallback for us.
hr = Marshal.GetLastWin32Error();
// For invalid handles, detect the error and mark our handle
// as closed to give slightly better error messages. Also
// help ensure we avoid handle recycling bugs.
if (hr == UnsafeNativeMethods.ERROR_INVALID_HANDLE)
_handle.SetHandleAsInvalid();
return -1;
}
else
hr = 0;
return numBytesWritten;
}
// This doesn't do argument checking. Necessary for SetLength, which must
// set the file pointer beyond the end of the file. This will update the
// internal position
//
//
//
//
//
//
[System.Security.SecurityCritical]
private long SeekCore(long offset, SeekOrigin origin)
{
Debug.Assert(!_handle.IsClosed, "!_handle.IsClosed");
Debug.Assert(origin>=SeekOrigin.Begin && origin<=SeekOrigin.End, "origin>=SeekOrigin.Begin && origin<=SeekOrigin.End");
int hr = 0;
long ret = 0;
ret = UnsafeNativeMethods.SetFilePointer(_handle, offset, origin, out hr);
if (ret == -1) {
// For invalid handles, detect the error and mark our handle
// as closed to give slightly better error messages. Also
// help ensure we avoid handle recycling bugs.
if (hr == UnsafeNativeMethods.ERROR_INVALID_HANDLE)
_handle.SetHandleAsInvalid();
__Error.WinIOError(hr, String.Empty);
}
UnderlyingStreamPosition = ret;
return ret;
}
//
//
//
//
[System.Security.SecurityCritical]
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 LogStream, which would often "just work" when
// finalized.
try {
if (_handle == null || _handle.IsClosed) {
// Make sure BufferedStream doesn't try to flush data on a closed handle
DiscardBuffer();
}
}
finally {
try {
// Cleanup base streams
base.Dispose(disposing);
}
finally {
if (_handle != null && !_handle.IsClosed)
_handle.Dispose();
_handle = null;
_canRead = false;
_canWrite = false;
_canSeek = false;
}
}
}
//
//
//
[System.Security.SecurityCritical]
~LogStream()
{
if (_handle != null) {
Dispose(false);
}
}
//
//
//
//
//
[System.Security.SecurityCritical]
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;
}
}
// When we enable this class widely, we need to raise an
// event when we disable logging due to rention policy or
// error such as ACL that is preventing retention
[MethodImplAttribute(MethodImplOptions.Synchronized)]
private void _DisableLogging()
{
// Discard write buffer?
_disableLogging = true;
}
//
//
//
[System.Security.SecurityCritical]
private static UnsafeNativeMethods.SECURITY_ATTRIBUTES GetSecAttrs(FileShare share)
{
UnsafeNativeMethods.SECURITY_ATTRIBUTES secAttrs = null;
if ((share & FileShare.Inheritable) != 0) {
secAttrs = new UnsafeNativeMethods.SECURITY_ATTRIBUTES();
secAttrs.nLength = (int)Marshal.SizeOf(secAttrs);
secAttrs.bInheritHandle = 1;
}
return secAttrs;
}
}
}
// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
Link Menu

This book is available now!
Buy at Amazon US or
Buy at Amazon UK
- FilteredReadOnlyMetadataCollection.cs
- BitmapCodecInfoInternal.cs
- LifetimeManager.cs
- ProcessModelInfo.cs
- PenCursorManager.cs
- DockEditor.cs
- ToolStripRenderer.cs
- ObjectListGeneralPage.cs
- X509SecurityTokenProvider.cs
- PassportPrincipal.cs
- SystemUnicastIPAddressInformation.cs
- DataListItemCollection.cs
- DataSourceGroupCollection.cs
- SocketInformation.cs
- RectAnimationClockResource.cs
- ResourceSetExpression.cs
- RectangleConverter.cs
- ZoomingMessageFilter.cs
- DecimalAnimationBase.cs
- GlyphInfoList.cs
- TextBounds.cs
- ObjectFactoryCodeDomTreeGenerator.cs
- GradientStopCollection.cs
- TextDecoration.cs
- MarshalByRefObject.cs
- DocumentViewer.cs
- ConfigWriter.cs
- COM2ComponentEditor.cs
- NodeInfo.cs
- XamlPoint3DCollectionSerializer.cs
- MessageSmuggler.cs
- PointAnimation.cs
- SoapExtensionTypeElementCollection.cs
- QilTypeChecker.cs
- BitmapPalette.cs
- CryptographicAttribute.cs
- Positioning.cs
- ImageList.cs
- DataServiceExpressionVisitor.cs
- InputProcessorProfiles.cs
- StoreConnection.cs
- WebBrowserPermission.cs
- HttpCapabilitiesSectionHandler.cs
- ListItemConverter.cs
- AnimationClockResource.cs
- SqlUserDefinedAggregateAttribute.cs
- DispatcherFrame.cs
- Constants.cs
- TextOutput.cs
- QuotedPrintableStream.cs
- SqlWorkflowInstanceStore.cs
- CounterSampleCalculator.cs
- Timeline.cs
- BitmapMetadataBlob.cs
- DataGridViewLinkColumn.cs
- FilteredAttributeCollection.cs
- ConnectionPoint.cs
- CharacterMetrics.cs
- MultiTrigger.cs
- RoleGroupCollection.cs
- PaintValueEventArgs.cs
- MetadataWorkspace.cs
- FunctionNode.cs
- LinqDataSourceDisposeEventArgs.cs
- ImageConverter.cs
- HScrollProperties.cs
- StringConverter.cs
- HostingMessageProperty.cs
- ApplicationException.cs
- DBConcurrencyException.cs
- COAUTHIDENTITY.cs
- ReliabilityContractAttribute.cs
- DataComponentGenerator.cs
- EntityModelSchemaGenerator.cs
- ScriptControlDescriptor.cs
- ServiceChannel.cs
- Columns.cs
- MissingMethodException.cs
- SurrogateChar.cs
- BinaryMethodMessage.cs
- ReadOnlyHierarchicalDataSourceView.cs
- ContentFilePart.cs
- AsymmetricSignatureFormatter.cs
- MailAddressCollection.cs
- GiveFeedbackEventArgs.cs
- PropertyGrid.cs
- ButtonFlatAdapter.cs
- DBAsyncResult.cs
- CopyNamespacesAction.cs
- FontCacheUtil.cs
- WebPartPersonalization.cs
- FastEncoder.cs
- AudioException.cs
- SqlLiftWhereClauses.cs
- ResolveNameEventArgs.cs
- Panel.cs
- ExtendedProtectionPolicyTypeConverter.cs
- Repeater.cs
- GlyphInfoList.cs
- MergeLocalizationDirectives.cs