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
- TransformCryptoHandle.cs
- Byte.cs
- VisualStyleElement.cs
- ConstrainedGroup.cs
- FileUtil.cs
- StyleBamlRecordReader.cs
- SqlNode.cs
- WmlControlAdapter.cs
- Padding.cs
- printdlgexmarshaler.cs
- CustomAttributeFormatException.cs
- HashHelper.cs
- Rect.cs
- DataGridDesigner.cs
- MappingItemCollection.cs
- IItemContainerGenerator.cs
- AutoResizedEvent.cs
- ServiceCredentials.cs
- PageCatalogPart.cs
- NoClickablePointException.cs
- Profiler.cs
- ConfigurationManagerHelperFactory.cs
- CompositeControl.cs
- ThicknessConverter.cs
- HttpRequest.cs
- Sql8ConformanceChecker.cs
- XmlDownloadManager.cs
- DiagnosticsConfigurationHandler.cs
- TransformValueSerializer.cs
- GeometryHitTestParameters.cs
- EventData.cs
- Page.cs
- TemplateParser.cs
- LazyTextWriterCreator.cs
- WindowsFont.cs
- ContextStack.cs
- InternalCache.cs
- SqlException.cs
- ContainerParagraph.cs
- ValueTable.cs
- ConstructorBuilder.cs
- NamedPipeHostedTransportConfiguration.cs
- DependentList.cs
- FieldMetadata.cs
- SpellerHighlightLayer.cs
- StreamGeometry.cs
- ScriptingSectionGroup.cs
- PingOptions.cs
- EntityDataSourceSelectedEventArgs.cs
- EncryptedData.cs
- WindowsListBox.cs
- FixedFlowMap.cs
- BamlTreeUpdater.cs
- ConfigurationLoader.cs
- DirectoryLocalQuery.cs
- MenuBindingsEditor.cs
- RequestStatusBarUpdateEventArgs.cs
- List.cs
- ColumnResult.cs
- GridViewSortEventArgs.cs
- DetailsViewRow.cs
- ExtensionWindowHeader.cs
- WebPartVerbsEventArgs.cs
- WebServiceClientProxyGenerator.cs
- Normalization.cs
- TraceUtils.cs
- ExpressionConverter.cs
- DocumentPageView.cs
- FrugalList.cs
- ClientSideQueueItem.cs
- Operand.cs
- DataGridBoundColumn.cs
- ImageMapEventArgs.cs
- MemberExpression.cs
- FontInfo.cs
- HttpException.cs
- QilTernary.cs
- CodeThrowExceptionStatement.cs
- InvalidProgramException.cs
- DefaultBinder.cs
- CodeSnippetExpression.cs
- DetailsViewDeleteEventArgs.cs
- ComponentDesigner.cs
- KeyBinding.cs
- GridPatternIdentifiers.cs
- MenuItemCollection.cs
- MouseGestureValueSerializer.cs
- OracleConnectionStringBuilder.cs
- WebPartCollection.cs
- SimpleModelProvider.cs
- CultureInfoConverter.cs
- StoreItemCollection.cs
- StrokeSerializer.cs
- MethodToken.cs
- ListParaClient.cs
- ColorAnimation.cs
- ListInitExpression.cs
- KnownTypeHelper.cs
- PropertyInformationCollection.cs
- RoleServiceManager.cs