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
- HtmlListAdapter.cs
- Model3D.cs
- HtmlInputHidden.cs
- WebPartEditorApplyVerb.cs
- DependencyPropertyValueSerializer.cs
- Converter.cs
- _DomainName.cs
- SecureUICommand.cs
- SafeNativeMethodsCLR.cs
- TargetException.cs
- TypefaceMap.cs
- PenThreadPool.cs
- DbConnectionPoolIdentity.cs
- ColorKeyFrameCollection.cs
- NativeMethods.cs
- ParseElementCollection.cs
- ConvertBinder.cs
- InvalidBodyAccessException.cs
- RightsManagementLicense.cs
- CacheOutputQuery.cs
- XmlSchemaValidator.cs
- ActivityMetadata.cs
- ToolStripCodeDomSerializer.cs
- DesignerOptionService.cs
- ServiceObjectContainer.cs
- ViewStateAttachedPropertyFeature.cs
- OpCellTreeNode.cs
- MTConfigUtil.cs
- BrowserDefinition.cs
- GridSplitter.cs
- GeometryGroup.cs
- EntityDataSourceChangedEventArgs.cs
- PhonemeConverter.cs
- FileSystemInfo.cs
- FixedPageStructure.cs
- EnterpriseServicesHelper.cs
- LogLogRecord.cs
- AddInPipelineAttributes.cs
- WebBrowserUriTypeConverter.cs
- FormsAuthenticationCredentials.cs
- OperationAbortedException.cs
- GroupedContextMenuStrip.cs
- GridItem.cs
- ProgressiveCrcCalculatingStream.cs
- BitmapEffectInputData.cs
- JapaneseCalendar.cs
- ButtonChrome.cs
- FormsAuthenticationUser.cs
- PropertyPathConverter.cs
- Int64AnimationUsingKeyFrames.cs
- HttpWebResponse.cs
- Win32KeyboardDevice.cs
- AssemblyUtil.cs
- MiniModule.cs
- DuplicateWaitObjectException.cs
- ExceptionAggregator.cs
- AQNBuilder.cs
- AccessDataSourceDesigner.cs
- ContainerAction.cs
- AnnotationResource.cs
- DataGridParentRows.cs
- Adorner.cs
- DataViewManager.cs
- PriorityItem.cs
- StaticSiteMapProvider.cs
- XmlNodeChangedEventManager.cs
- SecurityTokenReferenceStyle.cs
- UriSchemeKeyedCollection.cs
- XmlNavigatorStack.cs
- WindowsListViewGroupSubsetLink.cs
- SqlGenericUtil.cs
- HttpCapabilitiesEvaluator.cs
- _ListenerAsyncResult.cs
- MissingSatelliteAssemblyException.cs
- XmlCodeExporter.cs
- Debugger.cs
- ThousandthOfEmRealDoubles.cs
- StateChangeEvent.cs
- HyperLinkStyle.cs
- XPathMultyIterator.cs
- AnimationException.cs
- Point3DConverter.cs
- PropertyTabAttribute.cs
- EntitySqlQueryCacheKey.cs
- Baml2006KeyRecord.cs
- CodeFieldReferenceExpression.cs
- TimeSpan.cs
- MarkupWriter.cs
- DataControlFieldCell.cs
- WebPartDisplayModeCollection.cs
- ClaimSet.cs
- ParseElementCollection.cs
- Base64Stream.cs
- cryptoapiTransform.cs
- ProfileService.cs
- ComNativeDescriptor.cs
- BulletedList.cs
- DesignDataSource.cs
- WebBrowserBase.cs
- DefaultTextStore.cs