Code:
/ DotNET / DotNET / 8.0 / untmp / WIN_WINDOWS / lh_tools_devdiv_wpf / Windows / wcp / TrustUi / MS / Internal / documents / Application / FileController.cs / 1 / FileController.cs
//------------------------------------------------------------------------------ //// Copyright (C) Microsoft Corporation. All rights reserved. // //// Responsible for the lifecycle of the FileDocument and the actions that can // be performed on it. // // // History: // 08/28/2005: [....]: Initial implementation. //----------------------------------------------------------------------------- using System; using System.IO; using System.Security; using MS.Internal.Security; // AttachmentService namespace MS.Internal.Documents.Application { ////// Responsible for the lifecycle of the FileDocument and the actions that can /// be performed on it. /// internal class FileController : IDocumentController { #region IDocumentController Members //------------------------------------------------------------------------- // IDocumentController Members //------------------------------------------------------------------------- ////// /// ////// /// Critical: /// - calls DocumentStream.CreateTemporary /// - sets WorkspaceProxy with result DocumentStream.CreateTemporary /// TreatAsSafe: /// - ensures CreateTemporary is called once (mitigates DoS) /// - value for WorkspaceProxy derives from SourceProxy which is critical /// (safe value) /// [SecurityCritical, SecurityTreatAsSafe] bool IDocumentController.EnableEdit(Document document) { FileDocument doc = (FileDocument)document; if (doc.WorkspaceProxy == null) { // Try to obtain an exclusive lock on the source file. If this // fails, we can still create a temporary file and Save As to a // different location. bool canWriteToSource = doc.SourceProxy.ReOpenWriteable(); DocumentManager documentManager = DocumentManager.CreateDefault(); // We can save to the source file if we could reopen it for write if (documentManager != null) { documentManager.CanSave = canWriteToSource; } doc.WorkspaceProxy = doc.SourceProxy.CreateTemporary(false); if (doc.WorkspaceProxy == null) { FilePresentation.ShowNoTemporaryFileAccess(); } } return (doc.WorkspaceProxy != null); } ////// ////// /// Critical: /// - sets SourceProxy with result DocumentStream.Open /// - calls critical InitializeCurrentDocumentProperties using critical Uri /// TreatAsSafe: /// - ensures Open is called once (mitigates DoS) /// - value for SourceProxy derives from FileDocument.SourceToken /// which is critical (safe value) /// - Uri is critical in DocumentProperties thus not leaked and critical in /// Document (sourced from IE) thus safe for InitializeCurrentDocumentProperties /// although this extends the exposure of the Uri, this is by design as /// DocumentProperties uses it to display the value to the user who orginally /// provided it (not leaked User to User) /// [SecurityCritical, SecurityTreatAsSafe] bool IDocumentController.Open(Document document) { FileDocument doc = (FileDocument)document; if (doc.Source == null) { try { doc.SourceProxy = DocumentStream.Open(doc, false); } catch (UnauthorizedAccessException uae) { FilePresentation.ShowNoAccessToSource(); doc.SourceProxy = null; Trace.SafeWrite( Trace.File, "Unable to open specified location.\nException: {0}", uae); return false; } catch (IOException ioe) { FilePresentation.ShowNoAccessToSource(); doc.SourceProxy = null; Trace.SafeWrite( Trace.File, "Unable to open specified location.\nException: {0}", ioe); return false; } } DocumentProperties.InitializeCurrentDocumentProperties(doc.Uri); return true; } ////// ////// /// Critical: /// - sets SourceProxy which is critical /// TreatAsSafe: /// - SourceProxy's new value is null (which is safe) /// [SecurityCritical, SecurityTreatAsSafe] bool IDocumentController.Rebind(Document document) { FileDocument doc = (FileDocument)document; if (doc.IsRebindNeeded) { doc.SourceProxy.Close(); doc.SourceProxy = null; try { doc.SourceProxy = DocumentStream.Open(doc, false); } catch (UnauthorizedAccessException uae) { FilePresentation.ShowNoAccessToSource(); doc.SourceProxy = null; Trace.SafeWrite( Trace.File, "Unable to reopen specified location.\nException: {0}", uae); return false; } catch (IOException ioe) { FilePresentation.ShowNoAccessToSource(); doc.SourceProxy = null; Trace.SafeWrite( Trace.File, "Unable to reopen specified location.\nException: {0}", ioe); return false; } } return true; } ////// ////// /// Critical: /// - accesses CriticalFileTokens /// - sets DestinationProxy /// - calls DocumentStream.CreateTemporary /// - sets Document.IsDestinationIdenticalToSource /// TreatAsSafe: /// - only provides tokens to FilePresentation which is authorized by /// definition to disclose the information & to DocumentStream which /// does not leak them (safe from disclosure) & to StreamDocument which /// also does not leak them /// - DestinationProxy is derived either from CriticalFileTokens or from /// SourceProxy both are critical (safe value) /// - DocumentStream.CreateTemporary is called only based on user /// interaction or to update existing file (mitigates DoS) /// - Document.IsDestinationIdenticalToSource is set to the appropriate /// value depending on whether or not the destination file is actually /// identical to the source file. We save the value of IsFileCopySafe to /// ensure that this does not change between where we determine the /// appropriate action and where we actually take the action. /// [SecurityCritical, SecurityTreatAsSafe] bool IDocumentController.SaveAsPreperation(Document document) { FileDocument doc = (FileDocument)document; CriticalFileToken sourceToken = doc.SourceToken; CriticalFileToken saveToken = doc.DestinationToken; //---------------------------------------------------------------------- // Get Save Location and Consent (if needed) bool haveConsent = false; bool cancelSave = false; // Loop until we have consent to save to a file or the user cancels while (!haveConsent && !cancelSave) { // If we have a location, check to see if it is read-only if (saveToken != null) { if (DocumentStream.IsReadOnly(saveToken)) { // If the target file is read-only, we cannot save over it FilePresentation.ShowDestinationIsReadOnly(); } else { // If the file isn't read-only, we now have consent to save haveConsent = true; } } if (!haveConsent) { Trace.SafeWrite( Trace.File, "We don't have a save location, prompting user."); // by default set the same file if (saveToken == null) { saveToken = sourceToken; } // A false return value indicates that the user wanted to // cancel the save cancelSave = !FilePresentation.ShowSaveFileDialog(ref saveToken); } else { // Otherwise we do have consent to save to the location stored in // the saveToken doc.DestinationToken = saveToken; } } // Validate: If still don't have consent return without saving if (!haveConsent) { // ensure token is rescinded doc.DestinationToken = null; Trace.SafeWrite( Trace.File, "{0} not handling we do not have user consent.", this); return false; } bool isFileCopySafe = doc.IsFileCopySafe; //--------------------------------------------------------------------- // Calculate Save Action SaveAction action = SaveAction.Unknown; if (doc.Source.CanWrite) { action |= SaveAction.SourceIsWriteable; } if (sourceToken == saveToken) { action |= SaveAction.TargetIsSelf; } if (isFileCopySafe) { action |= SaveAction.CanCopyData; } bool isDestinationIdentical = false; // Catch IO Exceptions; will return false and clear token try { //---------------------------------------------------------------------- // Perform Optimal Save Action (see method remarks) switch (action) { // Example: We were successfully able to open the source package // for write and there were no RM changes. // I/O Cost: Read & SafeWrite Changes case SaveAction.TargetIsSelf | SaveAction.SourceIsWriteable | SaveAction.CanCopyData: Trace.SafeWrite( Trace.File, "SaveAction {0}: Updating comparee to self.", action); doc.DestinationProxy = doc.SourceProxy; isDestinationIdentical = true; break; // Example: Another user / process had a lock on the file, however // we would like to save now and there were no RM changes. // I/O Cost: Varies (Read & SafeWrite Changes - Read & SafeWrite Sum) case SaveAction.TargetIsSelf | SaveAction.CanCopyData: Trace.SafeWrite( Trace.File, "SaveAction {0}: reopening editable, updating comparee to self.", action); // re-open writeable if possible otherwise copy the file if (doc.SourceProxy.ReOpenWriteable()) { doc.DestinationProxy = doc.SourceProxy; isDestinationIdentical = true; } else { Trace.SafeWrite( Trace.File, "SaveAction {0}: creating a temporary document reopen failed.", action); doc.DestinationProxy = doc.SourceProxy.CreateTemporary(true); doc.SwapDestination = true; } break; case SaveAction.TargetIsSelf | SaveAction.SourceIsWriteable: case SaveAction.TargetIsSelf: Trace.SafeWrite( Trace.File, "SaveAction {0}: creating a temporary document.", action); doc.DestinationProxy = doc.SourceProxy.CreateTemporary(false); doc.SwapDestination = true; break; // Example: All other cases, like source is web based. // I/O Cost: Max (Read Sum & SafeWrite Sum) default: Trace.SafeWrite( Trace.File, "SaveAction {0}: Performing defaults.", action); if (isFileCopySafe) { Trace.SafeWrite( Trace.File, "SaveAction {0}: copying original document.", action); doc.DestinationProxy = doc.SourceProxy.Copy(saveToken); isDestinationIdentical = true; } else { doc.DestinationProxy = DocumentStream.Open(saveToken, true); // ensure we have enough quota to be as large as the sum doc.DestinationProxy.SetLength( doc.SourceProxy.Length + (doc.WorkspaceProxy == null ? 0 : doc.WorkspaceProxy.Length)); // set it back as we don't do the copy doc.DestinationProxy.SetLength(0); } doc.SwapDestination = false; break; } // switch (action) // Set the IsDestinationIdenticalToSource flag on the document // depending on what happened above doc.IsDestinationIdenticalToSource = isDestinationIdentical; return true; } catch (UnauthorizedAccessException uae) { FilePresentation.ShowNoAccessToDestination(); doc.DestinationProxy = null; // ensure token is recinded doc.DestinationToken = null; Trace.SafeWrite( Trace.File, "SaveAction {0}: unable to open specified location.\nException: {1}", action, uae); return false; } catch (IOException ioe) { FilePresentation.ShowNoAccessToDestination(); doc.DestinationProxy = null; // ensure token is recinded doc.DestinationToken = null; Trace.SafeWrite( Trace.File, "SaveAction {0}: unable to set size at specified location.\nException: {1}", action, ioe); return false; } } ////// ////// /// Critical: /// - accesses & sets CriticalFileToken /// - sets Uri for document /// TreatAsSafe: /// - checks if token is null and may use Location to set uri /// (no leak of token) /// - sets token to null (safe data) /// - document Uri is being set from CriticalFileToken (trusted data) /// [SecurityCritical, SecurityTreatAsSafe] bool IDocumentController.SaveCommit(Document document) { bool success = true; FileDocument doc = (FileDocument)document; bool haveConsent = (doc.DestinationToken != null); // Validate: If we have consent, if not return doing nothing. if (!haveConsent) { Trace.SafeWrite( Trace.File, "{0}.SaveCommit handling but doing nothing we do not have user consent.", this); return true; } doc.DestinationProxy.Flush(); //---------------------------------------------------------------------- // Swap Files if Needed if (doc.SwapDestination) { if (doc.DestinationProxy.SwapWithOriginal()) { Trace.SafeWrite( Trace.File, "SaveCommit has swapped Destination and Source file."); } else { success = false; FilePresentation.ShowNoAccessToDestination(); Trace.SafeWrite( Trace.File, "SaveCommit did not succeed because a needed file swap failed."); } // we attempted the operation turn off the request doc.SwapDestination = false; } if (success) { //----------------------------------------------------------------- // Rebind / Reload the Document if (doc.SourceToken == doc.DestinationToken) { // we changed the underlying data new keys may be required and // document policy may need re-evaluating or lost our reference doc.IsRebindNeeded = true; Trace.SafeWrite( Trace.File, "SaveCommit declaring a rebind is needed."); } else { Uri originalUri = doc.Uri; // we are a new document and we should be reloaded doc.Uri = doc.DestinationToken.Location; doc.IsReloadNeeded = true; // we are releasing our lock on the destination doc.DestinationProxy.Close(); doc.DestinationProxy = null; Trace.SafeWrite( Trace.File, "SaveCommit declaring a reload to {0} is needed.", doc.Uri); //------------------------------------------------------------------ // Add Mark of Web // This only needs to be done when the DestinationToken is in a // different location from the SourceToken, and the equality // operator on CriticalFileToken does properly compare the URI. Trace.SafeWrite( Trace.File, "AttachmentService.SaveWithUI from {0} to {1}.", originalUri, doc.DestinationToken.Location); AttachmentService.SaveWithUI( IntPtr.Zero, originalUri, doc.DestinationToken.Location); } } // rescinding user consent as save is completed doc.DestinationToken = null; return success; } ////// ////// /// Critical: /// - accesses CriticalFileTokens /// TreatAsSafe: /// - we are saving the in memory document back to the local file /// the token is being use for the same document /// [SecurityCritical, SecurityTreatAsSafe] bool IDocumentController.SavePreperation(Document document) { FileDocument doc = (FileDocument)document; doc.DestinationToken = doc.SourceToken; return ((IDocumentController)this).SaveAsPreperation(document); } #endregion IDocumentController Members #region IChainOfResponsibiltyNodeMembers //------------------------------------------------------------------------- // IChainOfResponsibiltyNode Members //------------------------------------------------------------------------- /// /// bool IChainOfResponsibiltyNode/// .IsResponsible(Document subject) { return subject is FileDocument; } #endregion IChainOfResponsibiltyNode Members /// /// Represents the type of save action to perform. /// [Flags] private enum SaveAction { ////// Unsure what action to take. /// Unknown = 0, ////// The Destination document has the same location as the Source. /// TargetIsSelf = 1, ////// The Source document was opened writeable. /// SourceIsWriteable = 2, ////// Copying the data at the file level is a safe operation. /// CanCopyData = 4 } } } // File provided for Reference Use Only by Microsoft Corporation (c) 2007. // Copyright (c) Microsoft Corporation. All rights reserved.
Link Menu
This book is available now!
Buy at Amazon US or
Buy at Amazon UK
- PageCatalogPartDesigner.cs
- EntityTypeEmitter.cs
- LinqDataSourceDeleteEventArgs.cs
- WinFormsSecurity.cs
- PageOrientation.cs
- ScrollItemPattern.cs
- ExtenderProviderService.cs
- RegexCode.cs
- WebPartEditVerb.cs
- PointCollectionValueSerializer.cs
- SimpleBitVector32.cs
- SmtpAuthenticationManager.cs
- RadioButton.cs
- SoapEnvelopeProcessingElement.cs
- Highlights.cs
- XmlQualifiedName.cs
- PtsContext.cs
- AppDomainGrammarProxy.cs
- ListBase.cs
- ModulesEntry.cs
- hwndwrapper.cs
- SessionIDManager.cs
- Int64.cs
- AuthenticationManager.cs
- CodeDOMProvider.cs
- XmlDataLoader.cs
- Model3DGroup.cs
- WindowsFormsHost.cs
- BmpBitmapDecoder.cs
- ServiceHostingEnvironmentSection.cs
- BindMarkupExtensionSerializer.cs
- DataGridViewToolTip.cs
- Point4DConverter.cs
- Delegate.cs
- AffineTransform3D.cs
- XslNumber.cs
- TreeNodeSelectionProcessor.cs
- RelatedImageListAttribute.cs
- DeploymentSection.cs
- OdbcEnvironmentHandle.cs
- DeploymentExceptionMapper.cs
- DataGridViewCellCollection.cs
- ComponentSerializationService.cs
- BindingList.cs
- SerializerWriterEventHandlers.cs
- FilePrompt.cs
- KeyedCollection.cs
- StringValidatorAttribute.cs
- ToolStripStatusLabel.cs
- XmlSchemaSimpleContent.cs
- XPathDocumentNavigator.cs
- ApplicationCommands.cs
- ConnectorSelectionGlyph.cs
- SqlDataReader.cs
- SafeMarshalContext.cs
- ObjectParameterCollection.cs
- initElementDictionary.cs
- BrushConverter.cs
- ActivityCodeGenerator.cs
- OleDbTransaction.cs
- RunWorkerCompletedEventArgs.cs
- Transform3DGroup.cs
- ConfigurationManagerInternalFactory.cs
- SecureStringHasher.cs
- connectionpool.cs
- ElementAction.cs
- UriWriter.cs
- XNodeNavigator.cs
- VerificationAttribute.cs
- CalendarDateRangeChangingEventArgs.cs
- HtmlInputControl.cs
- XPathMultyIterator.cs
- MemberHolder.cs
- GroupDescription.cs
- CacheDict.cs
- WebPartEditorOkVerb.cs
- wgx_commands.cs
- DisableDpiAwarenessAttribute.cs
- SqlDataSourceCache.cs
- CodeCatchClauseCollection.cs
- mediaclock.cs
- PageAsyncTask.cs
- OperationValidationEventArgs.cs
- VisualTransition.cs
- AuthenticationManager.cs
- WindowsAuthenticationEventArgs.cs
- StaticExtension.cs
- EditorPartChrome.cs
- DoneReceivingAsyncResult.cs
- Token.cs
- BinaryFormatterSinks.cs
- ProfilePropertySettingsCollection.cs
- DataGridHyperlinkColumn.cs
- UshortList2.cs
- MissingManifestResourceException.cs
- WebInvokeAttribute.cs
- TextDpi.cs
- SessionPageStatePersister.cs
- CharacterShapingProperties.cs
- FileSecurity.cs