Code:
/ Net / Net / 3.5.50727.3053 / DEVDIV / depot / DevDiv / releases / whidbey / netfxsp / ndp / fx / src / Configuration / System / Configuration / Internal / WriteFileContext.cs / 1 / WriteFileContext.cs
//------------------------------------------------------------------------------ //// Copyright (c) Microsoft Corporation. All rights reserved. // //----------------------------------------------------------------------------- namespace System.Configuration.Internal { using System.Configuration; using System.IO; using System.Security.Permissions; using System.Reflection; using System.Threading; using System.Security; using System.CodeDom.Compiler; using Microsoft.Win32; #if !FEATURE_PAL using System.Security.AccessControl; #endif internal class WriteFileContext { private const int SAVING_TIMEOUT = 10000; // 10 seconds private const int SAVING_RETRY_INTERVAL = 100; // 100 milliseconds private static bool _osPlatformDetermined; private static PlatformID _osPlatform; private TempFileCollection _tempFiles; private string _tempNewFilename; private string _templateFilename; internal WriteFileContext(string filename, string templateFilename) { string directoryname = UrlPath.GetDirectoryOrRootName(filename); _templateFilename = templateFilename; _tempFiles = new TempFileCollection(directoryname); try { _tempNewFilename = _tempFiles.AddExtension("newcfg"); } catch { ((IDisposable)_tempFiles).Dispose(); _tempFiles = null; throw; } } static WriteFileContext() { _osPlatformDetermined = false; } internal string TempNewFilename { get {return _tempNewFilename;} } // Complete // // Cleanup the WriteFileContext object based on either success // or failure // // Note: The current algorithm guarantess // 1) The file we are saving to will always be present // on the file system (ie. there will be no window // during saving in which there won't be a file there) // 2) It will always be available for reading from a // client and it will be complete and accurate. // // ... This means that writing is a bit more complicated, and may // have to be retried (because of reading lock), but I don't see // anyway to get around this given 1 and 2. // internal void Complete(string filename, bool success) { try { if (success) { if ( File.Exists( filename ) ) { // Test that we can write to the file ValidateWriteAccess( filename ); // Copy Attributes from original DuplicateFileAttributes( filename, _tempNewFilename ); } else { if ( _templateFilename != null ) { // Copy Acl from template file DuplicateTemplateAttributes( _templateFilename, _tempNewFilename ); } } ReplaceFile(_tempNewFilename, filename); // Don't delete, since we just moved it. _tempFiles.KeepFiles = true; } } finally { ((IDisposable)_tempFiles).Dispose(); _tempFiles = null; } } // DuplicateFileAttributes // // Copy all the files attributes that we care about from the source // file to the destination file // private void DuplicateFileAttributes( string source, string destination ) { #if !FEATURE_PAL FileAttributes attributes; DateTime creationTime; // Copy File Attributes, ie. Hidden, Readonly, etc. attributes = File.GetAttributes( source ); File.SetAttributes( destination, attributes ); // Copy Creation Time creationTime = File.GetCreationTimeUtc( source ); File.SetCreationTimeUtc( destination, creationTime ); // Copy ACL's DuplicateTemplateAttributes( source, destination ); #endif // FEATURE_PAL } // DuplicateTemplateAttributes // // Copy over all the attributes you would want copied from a template file. // As of right now this is just acl's // private void DuplicateTemplateAttributes( string source, string destination ) { #if !FEATURE_PAL if (IsWinNT) { FileSecurity fileSecurity; // Copy Security information fileSecurity = File.GetAccessControl( source, AccessControlSections.Access ); // Mark dirty, so effective for write fileSecurity.SetAccessRuleProtection( fileSecurity.AreAccessRulesProtected, true ); File.SetAccessControl( destination, fileSecurity ); } else { FileAttributes fileAttributes; fileAttributes = File.GetAttributes( source ); File.SetAttributes( destination, fileAttributes ); } #endif // FEATURE_PAL } // ValidateWriteAccess // // Validate that we can write to the file. This will enforce the ACL's // on the file. Since we do our moving of files to replace, this is // nice to ensure we are not by-passing some security permission // that someone set (although that could bypass this via move themselves) // // Note: 1) This is really just a nice to have, since with directory permissions // they could do the same thing we are doing // // 2) We are depending on the current behavior that if the file is locked // and we can not open it, that we will get an UnauthorizedAccessException // and not the IOException. // private void ValidateWriteAccess( string filename ) { FileStream fs = null; try { // Try to open file for write access fs = new FileStream( filename, FileMode.Open, FileAccess.Write, FileShare.ReadWrite ); } catch ( UnauthorizedAccessException ) { // Access was denied, make sure we throw this throw; } catch ( IOException ) { // Someone else was using the file. Since we did not get // the unauthorizedAccessException we have access to the file } catch ( Exception ) { // Unexpected, so just throw for safety sake throw; } finally { if ( fs != null ) { fs.Close(); } } } // ReplaceFile // // Replace one file with another using MoveFileEx. This will // retry the operation if the file is locked because someone // is reading it // private void ReplaceFile( string Source, string Target ) { bool WriteSucceeded = false; int Duration = 0; WriteSucceeded = AttemptMove( Source, Target ); // The file may be open for read, if it is then // lets try again because maybe they will finish // soon, and we will be able to replace while ( !WriteSucceeded && ( Duration < SAVING_TIMEOUT ) && File.Exists( Target ) && !FileIsWriteLocked( Target ) ) { Thread.Sleep( SAVING_RETRY_INTERVAL ); Duration += SAVING_RETRY_INTERVAL; WriteSucceeded = AttemptMove( Source, Target ); } if ( !WriteSucceeded ) { throw new ConfigurationErrorsException( SR.GetString(SR.Config_write_failed, Target) ); } } // AttemptMove // // Attempt to move a file from one location to another // // Return Values: // TRUE - Move Successful // FALSE - Move Failed private bool AttemptMove( string Source, string Target ) { bool MoveSuccessful = false; if ( IsWinNT ) { // We can only call this when we have kernel32.dll MoveSuccessful = UnsafeNativeMethods.MoveFileEx( Source, Target, UnsafeNativeMethods.MOVEFILE_REPLACE_EXISTING ); } else { try { // VSWhidbey 548017: // File.Move isn't supported on Win9x. We'll use File.Copy // instead. Please note that Source is a temporary file which // will be deleted when _tempFiles is disposed. File.Copy(Source, Target, true); MoveSuccessful = true; } catch { MoveSuccessful = false; } } return MoveSuccessful; } // FileIsWriteLocked // // Is the file write locked or not? // private bool FileIsWriteLocked( string FileName ) { Stream FileStream = null; bool WriteLocked = true; if (!FileUtil.FileExists(FileName, true)) { // It can't be locked if it doesn't exist return false; } try { FileShare fileShare = FileShare.Read; if (IsWinNT) { fileShare |= FileShare.Delete; } // Try to open for shared reading FileStream = new FileStream( FileName, FileMode.Open, FileAccess.Read, fileShare); // If we can open it for shared reading, it is not // write locked WriteLocked = false; } finally { if ( FileStream != null ) { FileStream.Close(); FileStream = null; } } return WriteLocked; } // IsWinNT // // Are we running in WinNT or not? // private bool IsWinNT { get { if ( !_osPlatformDetermined ) { _osPlatform = Environment.OSVersion.Platform; _osPlatformDetermined = true; } return ( _osPlatform == System.PlatformID.Win32NT ); } } } } // File provided for Reference Use Only by Microsoft Corporation (c) 2007. //------------------------------------------------------------------------------ //// Copyright (c) Microsoft Corporation. All rights reserved. // //----------------------------------------------------------------------------- namespace System.Configuration.Internal { using System.Configuration; using System.IO; using System.Security.Permissions; using System.Reflection; using System.Threading; using System.Security; using System.CodeDom.Compiler; using Microsoft.Win32; #if !FEATURE_PAL using System.Security.AccessControl; #endif internal class WriteFileContext { private const int SAVING_TIMEOUT = 10000; // 10 seconds private const int SAVING_RETRY_INTERVAL = 100; // 100 milliseconds private static bool _osPlatformDetermined; private static PlatformID _osPlatform; private TempFileCollection _tempFiles; private string _tempNewFilename; private string _templateFilename; internal WriteFileContext(string filename, string templateFilename) { string directoryname = UrlPath.GetDirectoryOrRootName(filename); _templateFilename = templateFilename; _tempFiles = new TempFileCollection(directoryname); try { _tempNewFilename = _tempFiles.AddExtension("newcfg"); } catch { ((IDisposable)_tempFiles).Dispose(); _tempFiles = null; throw; } } static WriteFileContext() { _osPlatformDetermined = false; } internal string TempNewFilename { get {return _tempNewFilename;} } // Complete // // Cleanup the WriteFileContext object based on either success // or failure // // Note: The current algorithm guarantess // 1) The file we are saving to will always be present // on the file system (ie. there will be no window // during saving in which there won't be a file there) // 2) It will always be available for reading from a // client and it will be complete and accurate. // // ... This means that writing is a bit more complicated, and may // have to be retried (because of reading lock), but I don't see // anyway to get around this given 1 and 2. // internal void Complete(string filename, bool success) { try { if (success) { if ( File.Exists( filename ) ) { // Test that we can write to the file ValidateWriteAccess( filename ); // Copy Attributes from original DuplicateFileAttributes( filename, _tempNewFilename ); } else { if ( _templateFilename != null ) { // Copy Acl from template file DuplicateTemplateAttributes( _templateFilename, _tempNewFilename ); } } ReplaceFile(_tempNewFilename, filename); // Don't delete, since we just moved it. _tempFiles.KeepFiles = true; } } finally { ((IDisposable)_tempFiles).Dispose(); _tempFiles = null; } } // DuplicateFileAttributes // // Copy all the files attributes that we care about from the source // file to the destination file // private void DuplicateFileAttributes( string source, string destination ) { #if !FEATURE_PAL FileAttributes attributes; DateTime creationTime; // Copy File Attributes, ie. Hidden, Readonly, etc. attributes = File.GetAttributes( source ); File.SetAttributes( destination, attributes ); // Copy Creation Time creationTime = File.GetCreationTimeUtc( source ); File.SetCreationTimeUtc( destination, creationTime ); // Copy ACL's DuplicateTemplateAttributes( source, destination ); #endif // FEATURE_PAL } // DuplicateTemplateAttributes // // Copy over all the attributes you would want copied from a template file. // As of right now this is just acl's // private void DuplicateTemplateAttributes( string source, string destination ) { #if !FEATURE_PAL if (IsWinNT) { FileSecurity fileSecurity; // Copy Security information fileSecurity = File.GetAccessControl( source, AccessControlSections.Access ); // Mark dirty, so effective for write fileSecurity.SetAccessRuleProtection( fileSecurity.AreAccessRulesProtected, true ); File.SetAccessControl( destination, fileSecurity ); } else { FileAttributes fileAttributes; fileAttributes = File.GetAttributes( source ); File.SetAttributes( destination, fileAttributes ); } #endif // FEATURE_PAL } // ValidateWriteAccess // // Validate that we can write to the file. This will enforce the ACL's // on the file. Since we do our moving of files to replace, this is // nice to ensure we are not by-passing some security permission // that someone set (although that could bypass this via move themselves) // // Note: 1) This is really just a nice to have, since with directory permissions // they could do the same thing we are doing // // 2) We are depending on the current behavior that if the file is locked // and we can not open it, that we will get an UnauthorizedAccessException // and not the IOException. // private void ValidateWriteAccess( string filename ) { FileStream fs = null; try { // Try to open file for write access fs = new FileStream( filename, FileMode.Open, FileAccess.Write, FileShare.ReadWrite ); } catch ( UnauthorizedAccessException ) { // Access was denied, make sure we throw this throw; } catch ( IOException ) { // Someone else was using the file. Since we did not get // the unauthorizedAccessException we have access to the file } catch ( Exception ) { // Unexpected, so just throw for safety sake throw; } finally { if ( fs != null ) { fs.Close(); } } } // ReplaceFile // // Replace one file with another using MoveFileEx. This will // retry the operation if the file is locked because someone // is reading it // private void ReplaceFile( string Source, string Target ) { bool WriteSucceeded = false; int Duration = 0; WriteSucceeded = AttemptMove( Source, Target ); // The file may be open for read, if it is then // lets try again because maybe they will finish // soon, and we will be able to replace while ( !WriteSucceeded && ( Duration < SAVING_TIMEOUT ) && File.Exists( Target ) && !FileIsWriteLocked( Target ) ) { Thread.Sleep( SAVING_RETRY_INTERVAL ); Duration += SAVING_RETRY_INTERVAL; WriteSucceeded = AttemptMove( Source, Target ); } if ( !WriteSucceeded ) { throw new ConfigurationErrorsException( SR.GetString(SR.Config_write_failed, Target) ); } } // AttemptMove // // Attempt to move a file from one location to another // // Return Values: // TRUE - Move Successful // FALSE - Move Failed private bool AttemptMove( string Source, string Target ) { bool MoveSuccessful = false; if ( IsWinNT ) { // We can only call this when we have kernel32.dll MoveSuccessful = UnsafeNativeMethods.MoveFileEx( Source, Target, UnsafeNativeMethods.MOVEFILE_REPLACE_EXISTING ); } else { try { // VSWhidbey 548017: // File.Move isn't supported on Win9x. We'll use File.Copy // instead. Please note that Source is a temporary file which // will be deleted when _tempFiles is disposed. File.Copy(Source, Target, true); MoveSuccessful = true; } catch { MoveSuccessful = false; } } return MoveSuccessful; } // FileIsWriteLocked // // Is the file write locked or not? // private bool FileIsWriteLocked( string FileName ) { Stream FileStream = null; bool WriteLocked = true; if (!FileUtil.FileExists(FileName, true)) { // It can't be locked if it doesn't exist return false; } try { FileShare fileShare = FileShare.Read; if (IsWinNT) { fileShare |= FileShare.Delete; } // Try to open for shared reading FileStream = new FileStream( FileName, FileMode.Open, FileAccess.Read, fileShare); // If we can open it for shared reading, it is not // write locked WriteLocked = false; } finally { if ( FileStream != null ) { FileStream.Close(); FileStream = null; } } return WriteLocked; } // IsWinNT // // Are we running in WinNT or not? // private bool IsWinNT { get { if ( !_osPlatformDetermined ) { _osPlatform = Environment.OSVersion.Platform; _osPlatformDetermined = true; } return ( _osPlatform == System.PlatformID.Win32NT ); } } } } // 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
- HMACSHA256.cs
- DomainConstraint.cs
- SerTrace.cs
- SqlProvider.cs
- ResourceType.cs
- DataGridViewTextBoxColumn.cs
- XmlDigitalSignatureProcessor.cs
- DeclarativeCatalogPart.cs
- MailWriter.cs
- AllMembershipCondition.cs
- SliderAutomationPeer.cs
- FigureParaClient.cs
- BindStream.cs
- CustomError.cs
- DataGridViewAutoSizeColumnsModeEventArgs.cs
- WebPartMenu.cs
- XPathNodeIterator.cs
- TimeSpanMinutesConverter.cs
- TextBoxAutomationPeer.cs
- SelectedGridItemChangedEvent.cs
- SR.cs
- LambdaCompiler.ControlFlow.cs
- DrawingGroup.cs
- SafeRightsManagementSessionHandle.cs
- X509ChainPolicy.cs
- WindowsScrollBarBits.cs
- NotFiniteNumberException.cs
- CardSpaceSelector.cs
- ImportCatalogPart.cs
- FtpRequestCacheValidator.cs
- XsdBuildProvider.cs
- HashCodeCombiner.cs
- Subset.cs
- DesigntimeLicenseContext.cs
- ChildrenQuery.cs
- CodeStatementCollection.cs
- ConnectionConsumerAttribute.cs
- ApplicationId.cs
- ReachBasicContext.cs
- SignedPkcs7.cs
- DiscoveryProxy.cs
- SmtpLoginAuthenticationModule.cs
- DoubleIndependentAnimationStorage.cs
- CustomPopupPlacement.cs
- NativeMethods.cs
- SQLByte.cs
- StylusButton.cs
- LogSwitch.cs
- ClientUtils.cs
- BindableAttribute.cs
- HttpCacheVaryByContentEncodings.cs
- MenuItemBinding.cs
- EditingCommands.cs
- CharEnumerator.cs
- CustomLineCap.cs
- SetterBaseCollection.cs
- SqlConnectionHelper.cs
- AutoSizeToolBoxItem.cs
- RawStylusInputCustomDataList.cs
- ZipQueryOperator.cs
- OdbcDataReader.cs
- PeerNameResolver.cs
- MdiWindowListStrip.cs
- ConfigurationSectionGroup.cs
- HttpFileCollection.cs
- BuildProviderCollection.cs
- DataGridAutoFormat.cs
- CellCreator.cs
- TCEAdapterGenerator.cs
- XmlText.cs
- CategoryGridEntry.cs
- DllNotFoundException.cs
- WebPartCatalogCloseVerb.cs
- InProcStateClientManager.cs
- EncryptedKeyIdentifierClause.cs
- ExecutionContext.cs
- SQLSingle.cs
- ToolTip.cs
- ReflectionUtil.cs
- XmlSchemaAnyAttribute.cs
- OverloadGroupAttribute.cs
- ConfigXmlElement.cs
- DataTableClearEvent.cs
- BinHexEncoder.cs
- NumericUpDownAcceleration.cs
- EventProvider.cs
- IsolatedStorageSecurityState.cs
- ApplicationHost.cs
- TypeConstant.cs
- WebServiceHandlerFactory.cs
- UniformGrid.cs
- Parameter.cs
- SqlClientWrapperSmiStream.cs
- SqlDataSourceConfigureFilterForm.cs
- Freezable.cs
- NextPreviousPagerField.cs
- Bidi.cs
- EventLog.cs
- QueryCacheEntry.cs
- TrailingSpaceComparer.cs