Code:
/ Dotnetfx_Win7_3.5.1 / Dotnetfx_Win7_3.5.1 / 3.5.1 / DEVDIV / depot / DevDiv / releases / whidbey / NetFXspW7 / 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
- HierarchicalDataBoundControlAdapter.cs
- CacheMemory.cs
- RadialGradientBrush.cs
- TreeViewAutomationPeer.cs
- Bits.cs
- XsdValidatingReader.cs
- ActivityDesignerLayoutSerializers.cs
- OpacityConverter.cs
- TableColumnCollectionInternal.cs
- FaultReasonText.cs
- PropertyGrid.cs
- PrefixQName.cs
- StatusBarItem.cs
- RtfFormatStack.cs
- X509Chain.cs
- TemplateField.cs
- DataTableCollection.cs
- Point3DConverter.cs
- ByteAnimationBase.cs
- LinearGradientBrush.cs
- ObjectListGeneralPage.cs
- SystemInfo.cs
- ACL.cs
- Brushes.cs
- MailMessage.cs
- RSAOAEPKeyExchangeDeformatter.cs
- DataRowExtensions.cs
- _ShellExpression.cs
- Cloud.cs
- WindowsTreeView.cs
- CrossContextChannel.cs
- DataGridViewIntLinkedList.cs
- XPathDocumentBuilder.cs
- DataGridView.cs
- DynamicILGenerator.cs
- StatusStrip.cs
- NativeActivityAbortContext.cs
- Binding.cs
- MobileControlDesigner.cs
- AddInProcess.cs
- MetadataCacheItem.cs
- GridViewDesigner.cs
- DuplicateDetector.cs
- NativeRecognizer.cs
- SqlNotificationEventArgs.cs
- WorkflowRuntimeBehavior.cs
- DependencyObjectPropertyDescriptor.cs
- Stream.cs
- SqlClientMetaDataCollectionNames.cs
- ServiceXNameTypeConverter.cs
- FilterQuery.cs
- InheritedPropertyChangedEventArgs.cs
- EmptyEnumerable.cs
- EmptyArray.cs
- path.cs
- EventDescriptor.cs
- EditorOptionAttribute.cs
- DbParameterCollectionHelper.cs
- LookupNode.cs
- PropertyState.cs
- NamedElement.cs
- PathTooLongException.cs
- Message.cs
- WebPartConnectionCollection.cs
- MD5Cng.cs
- XmlnsDictionary.cs
- AutomationElementCollection.cs
- DispatcherExceptionFilterEventArgs.cs
- XmlName.cs
- DocumentSchemaValidator.cs
- BaseAutoFormat.cs
- EmptyQuery.cs
- WebServiceTypeData.cs
- DependencyObjectType.cs
- ValueSerializerAttribute.cs
- SerializationAttributes.cs
- DayRenderEvent.cs
- DataGridSortCommandEventArgs.cs
- StreamGeometry.cs
- FieldToken.cs
- XhtmlBasicTextViewAdapter.cs
- XamlTemplateSerializer.cs
- OleDbWrapper.cs
- CreateParams.cs
- cache.cs
- GenericIdentity.cs
- RuntimeConfigurationRecord.cs
- SettingsBindableAttribute.cs
- AttachmentService.cs
- TextEmbeddedObject.cs
- UndirectedGraph.cs
- DataGridViewCellStateChangedEventArgs.cs
- CompiledRegexRunnerFactory.cs
- HandledEventArgs.cs
- CacheSection.cs
- DoWorkEventArgs.cs
- WebPartCloseVerb.cs
- ControlSerializer.cs
- Pipe.cs
- LassoSelectionBehavior.cs