Code:
/ 4.0 / 4.0 / untmp / DEVDIV_TFS / Dev10 / Releases / RTMRel / ndp / fx / src / Configuration / System / Configuration / Internal / WriteFileContext.cs / 1305376 / 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.
Link Menu
This book is available now!
Buy at Amazon US or
Buy at Amazon UK
- ConstraintConverter.cs
- EntityContainer.cs
- SemanticBasicElement.cs
- Size.cs
- TimeSpanMinutesOrInfiniteConverter.cs
- ProfileSettings.cs
- ApplicationFileParser.cs
- HeaderLabel.cs
- DoubleAnimationClockResource.cs
- BinaryWriter.cs
- DeclarativeCatalogPart.cs
- InertiaTranslationBehavior.cs
- LogLogRecordEnumerator.cs
- DataGridItemCollection.cs
- AdapterDictionary.cs
- CompositeFontParser.cs
- ListControl.cs
- JsonSerializer.cs
- DifferencingCollection.cs
- ProfessionalColors.cs
- XmlDesigner.cs
- SafeProcessHandle.cs
- Attributes.cs
- GetBrowserTokenRequest.cs
- PlainXmlDeserializer.cs
- LogEntry.cs
- ECDiffieHellmanPublicKey.cs
- FixedSOMSemanticBox.cs
- TopClause.cs
- DbExpressionBuilder.cs
- PolicyException.cs
- ContextBase.cs
- SmtpException.cs
- ServiceContractViewControl.cs
- SerializationHelper.cs
- ProcessThread.cs
- ChangeProcessor.cs
- WebPartVerbsEventArgs.cs
- DateTimeFormatInfo.cs
- _HeaderInfo.cs
- OleServicesContext.cs
- Crc32Helper.cs
- InfocardChannelParameter.cs
- TransactionTraceIdentifier.cs
- Vertex.cs
- RenderDataDrawingContext.cs
- DesignerAttributeInfo.cs
- HMACRIPEMD160.cs
- OutputCacheProfile.cs
- DbTransaction.cs
- PersonalizableTypeEntry.cs
- AuthenticateEventArgs.cs
- BindingMAnagerBase.cs
- Win32SafeHandles.cs
- DataGridPageChangedEventArgs.cs
- HelpEvent.cs
- SpanIndex.cs
- FlowDocumentScrollViewerAutomationPeer.cs
- Random.cs
- InkPresenter.cs
- DataListItem.cs
- ScriptServiceAttribute.cs
- GetPageCompletedEventArgs.cs
- ECDsaCng.cs
- GridSplitter.cs
- CachedTypeface.cs
- PauseStoryboard.cs
- ToolStripDropDownMenu.cs
- SqlCrossApplyToCrossJoin.cs
- EditorBrowsableAttribute.cs
- ConfigurationLocation.cs
- DoubleAnimationClockResource.cs
- ConditionChanges.cs
- ReadOnlyNameValueCollection.cs
- SafeBitVector32.cs
- AssociationTypeEmitter.cs
- ByteAnimation.cs
- Function.cs
- VScrollBar.cs
- TextContainer.cs
- regiisutil.cs
- IsolatedStorage.cs
- ReflectionPermission.cs
- Connector.cs
- DataGridViewElement.cs
- ValidationSummary.cs
- EntityTypeEmitter.cs
- CapabilitiesUse.cs
- Schema.cs
- WebAdminConfigurationHelper.cs
- SQLMoneyStorage.cs
- RoleGroup.cs
- PagePropertiesChangingEventArgs.cs
- WindowsListViewItem.cs
- LocatorPart.cs
- PersonalizableAttribute.cs
- StoragePropertyMapping.cs
- EncryptedXml.cs
- _ListenerResponseStream.cs
- StylusDownEventArgs.cs