Code:
/ DotNET / DotNET / 8.0 / untmp / WIN_WINDOWS / lh_tools_devdiv_wpf / Windows / wcp / Base / System / IO / Packaging / CompoundFile / StreamInfo.cs / 1 / StreamInfo.cs
//------------------------------------------------------------------------------ // //// Copyright (C) Microsoft Corporation. All rights reserved. // // // Description: // Class for manipulating streams in the container file // // History: // 05/13/2002: [....]: Initial implementation. // 06/25/2002: [....]: Data space support. // 07/31/2002: [....]: Make obvious that we are using security suppressed interfaces. // 05/20/2003: [....]: Ported to WCP tree. // 05/28/2003: [....]: Added long name support // //----------------------------------------------------------------------------- using System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; // For Debug.Assert using System.IO; using System.Runtime.InteropServices; using System.Security; using System.Security.Permissions; using System.Windows; // SR.Get(SRID.[exception message]) using MS.Internal.IO.Packaging.CompoundFile; using CU = MS.Internal.IO.Packaging.CompoundFile.ContainerUtilities; using System.IO.Packaging; namespace System.IO.Packaging { ////// Core information for a StreamInfo object. /// internal class StreamInfoCore { internal StreamInfoCore( string nameStream, string label ) : this( nameStream, label, null ) {;} internal StreamInfoCore( string nameStream, string label, IStream s ) { streamName = nameStream; dataSpaceLabel = label; safeIStream = s; exposedStream = null; } ////// The compound-file friendly version of streamName. /// internal string streamName; ////// A cached reference to the stream object for accessing the data This /// may be null if we haven't had need to open the stream. /// internal IStream safeIStream; ////// The label for the data space definition that is associated with this /// stream. This can only be set at the time of StreamInfo.Create(). A /// null string indicates that we are not in a data space. /// internal string dataSpaceLabel; ////// This represents visible stream object. When the stream represented by this StreamInfo is supposed /// to go away, this will be reset to null. /// internal object exposedStream; } ////// Class for manipulating streams in the container file /// public class StreamInfo { /***********************************************************************/ // Default values to use for shortcuts const FileMode defaultFileOpenMode = FileMode.OpenOrCreate; const FileMode defaultFileCreateMode = FileMode.Create; const string defaultDataSpace = null; // Programmatic change-able? /***********************************************************************/ // Instance values ////// A reference back to the parent storage object /// StorageInfo parentStorage; ////// Reference to a class that contains our core information. This is /// maintained by our parent storage. /// StreamInfoCore core; ////// CompoundFileStreamReference for this StreamInfo object /// CompoundFileStreamReference _streamReference; ////// We need to rememeber the FileAccess that was used for openning /// in order to provide correct information, we can not used underlying structures, /// as the same stream can be subsequently opened in different modes /// private FileAccess openFileAccess; private CompressionOption _compressionOption; private EncryptionOption _encryptionOption; private bool _needToGetTransformInfo = true; /***********************************************************************/ // Constructors private void BuildStreamInfoRelativeToStorage( StorageInfo parent, string path ) { parentStorage = parent; core = parentStorage.CoreForChildStream( path ); } ////// Creates a new instance relative to the root /// /// The root storage /// Path to stream under root storage private StreamInfo( StorageRoot root, string streamPath ) : this((StorageInfo)root, streamPath) { } ////// Creates a new instance relative to the given parent /// /// The parent storage /// Path to stream under parent storage internal StreamInfo( StorageInfo parent, string streamName ) : this (parent, streamName, CompressionOption.NotCompressed, EncryptionOption.None) { } ////// Creates a new instance relative to the given parent /// /// The parent storage /// Path to stream under parent storage /// CompressionOption /// EncryptionOption internal StreamInfo( StorageInfo parent, string streamName, CompressionOption compressionOption, EncryptionOption encryptionOption ) { // Parameter validation CU.CheckAgainstNull( parent, "parent" ); CU.CheckStringAgainstNullAndEmpty( streamName, "streamName" ); // Parse path relative to given parent. BuildStreamInfoRelativeToStorage( parent, streamName); _compressionOption = compressionOption; _encryptionOption = encryptionOption; _streamReference = new CompoundFileStreamReference(this.parentStorage.FullNameInternal, this.core.streamName); } /***********************************************************************/ // Properties ////// The CompressionOption on the stream /// public CompressionOption CompressionOption { get { if( StreamInfoDisposed ) // Null name in core signifies the core object is disposed { // The .Net Design Guidelines instruct us not to throw exceptions in property getters. return CompressionOption.NotCompressed; } EnsureTransformInformation(); return _compressionOption; } } ////// The EncryptionOption on the stream /// public EncryptionOption EncryptionOption { get { if( StreamInfoDisposed ) // Null name in core signifies the core object is disposed { // The .Net Design Guidelines instruct us not to throw exceptions in property getters. return EncryptionOption.None; } EnsureTransformInformation(); return _encryptionOption; } } ////// The name of this stream /// public string Name { get { if( StreamInfoDisposed ) // Null name in core signifies the core object is disposed { // The .Net Design Guidelines instruct us not to throw exceptions in property getters. return ""; } return core.streamName; } } /***********************************************************************/ // Methods ////// Opens a stream /// ///Stream object to manipulate data public Stream GetStream() { return GetStream( defaultFileOpenMode, parentStorage.Root.OpenAccess ); } ////// Opens a stream with the given open mode flags /// /// Open mode flags ///Stream object to manipulate data public Stream GetStream( FileMode mode ) { return GetStream( mode, parentStorage.Root.OpenAccess ); } ////// Opens a stream with the given open mode flags and access flags /// /// Open mode flags /// File access flags ///Stream object to manipulate data public Stream GetStream( FileMode mode, FileAccess access ) { CheckDisposedStatus(); int grfMode = 0; IStream openedIStream = null; openFileAccess = access; // becasue of the stream caching mechanism we must adjust FileAccess parameter. // We want to open stream with the widest access posible, in case Package was open in ReadWrite // we need to open stream in ReadWrite even if user explicitly asked us to do ReadOnly/WriteOnly. // There is a possibility of a next request coming in as as ReadWrite request, and we would like to // take advanatage of the cached stream by wrapping with appropriate access limitations. if (parentStorage.Root.OpenAccess == FileAccess.ReadWrite) { // Generate the access flags from the access parameter access = FileAccess.ReadWrite; } // Generate the access flags from the access parameter SafeNativeCompoundFileMethods.UpdateModeFlagFromFileAccess( access, ref grfMode ); // Only SHARE_EXCLUSIVE for now, FileShare issue TBD grfMode |= SafeNativeCompoundFileConstants.STGM_SHARE_EXCLUSIVE; CheckAccessMode(grfMode); // Act based on FileMode switch(mode) { case FileMode.Append: throw new ArgumentException( SR.Get(SRID.FileModeUnsupported)); case FileMode.Create: // Check to make sure root container is not read-only, and that // we're not pointlessly trying to create a read-only stream. CreateTimeReadOnlyCheck(openFileAccess); // Close down any existing streams floating out there if (null != core.exposedStream) { ((Stream)(core.exposedStream)).Close(); } core.exposedStream = null; if( null != core.safeIStream ) { // Close out existing stream ((IDisposable) core.safeIStream).Dispose(); core.safeIStream = null; } // Cleanup done, create new stream in its place grfMode |= SafeNativeCompoundFileConstants.STGM_CREATE; openedIStream = CreateStreamOnParentIStorage( core.streamName, grfMode ); break; case FileMode.CreateNew: throw new ArgumentException( SR.Get(SRID.FileModeUnsupported)); case FileMode.Open: // If we've got a stream, return a CFStream built from its clone if( null != core.safeIStream ) { return CFStreamOfClone(openFileAccess); } // Need to call Open API with NULL open flags openedIStream = OpenStreamOnParentIStorage( core.streamName, grfMode ); break; case FileMode.OpenOrCreate: // If we've got a stream, return a CFStream built from its clone if( null != core.safeIStream ) { return CFStreamOfClone(openFileAccess); } // Skip creation attempt for read-only container or specifying // read-only stream if( FileAccess.Read != parentStorage.Root.OpenAccess && FileAccess.Read != openFileAccess ) { // Try creating first. If it already exists then do an open. This // seems ugly but this method involves the fewest number of // managed/unmanaged transitions. if( !parentStorage.Exists ) { parentStorage.Create(); } int nativeCallErrorCode = parentStorage.SafeIStorage.CreateStream( core.streamName, grfMode, 0, 0, out openedIStream ); if( SafeNativeCompoundFileConstants.S_OK != nativeCallErrorCode && SafeNativeCompoundFileConstants.STG_E_FILEALREADYEXISTS != nativeCallErrorCode ) { throw new IOException( SR.Get(SRID.UnableToCreateStream), new COMException( SR.Get(SRID.NamedAPIFailure, "IStorage.CreateStream"), nativeCallErrorCode )); } // Parent storage has changed - invalidate all standing enuemrators parentStorage.InvalidateEnumerators(); // else - proceed with open } if( null == openedIStream ) { // If we make it here, it means the create stream call failed // because of a STG_E_FILEALREADYEXISTS // or container is read-only openedIStream = OpenStreamOnParentIStorage( core.streamName, grfMode ); } break; case FileMode.Truncate: throw new ArgumentException( SR.Get(SRID.FileModeUnsupported)); default: throw new ArgumentException( SR.Get(SRID.FileModeInvalid)); } core.safeIStream = openedIStream; Stream returnStream = BuildStreamOnUnderlyingIStream( core.safeIStream, openFileAccess, this ); core.exposedStream = returnStream; return returnStream; } /***********************************************************************/ // Internal/Private functionality ////// Creates a stream with all default parameters /// ///Stream object to manipulate data internal Stream Create() { return Create( defaultFileCreateMode, parentStorage.Root.OpenAccess, defaultDataSpace ); } ////// Creates a stream with the given create mode /// /// Desired create mode ///Stream object to manipulate data private Stream Create( FileMode mode ) { return Create( mode, parentStorage.Root.OpenAccess, defaultDataSpace ); } ////// Creates a stream encoded in the given data space /// /// Data space label ///Stream object to manipulate data internal Stream Create( string dataSpaceLabel ) { return Create( defaultFileCreateMode, parentStorage.Root.OpenAccess, dataSpaceLabel ); } ////// Creates a stream with the given create and access flags /// /// Desired create mode flag /// Access flags ///Stream object to manipulate data private Stream Create( FileMode mode, FileAccess access ) { return Create( mode, access, defaultDataSpace ); } ////// Creates a stream with the given parameters /// /// Creation mode /// Access mode /// Data space encoding ///Stream object to manipulate data internal Stream Create( FileMode mode, FileAccess access, string dataSpace ) { CheckDisposedStatus(); int grfMode = 0; IStream createdSafeIStream = null; DataSpaceManager dataSpaceManager = null; // Check to make sure root container is not read-only, and that // we're not pointlessly trying to create a read-only stream. CreateTimeReadOnlyCheck( access ); // Check to see if the data space label is valid if( null != dataSpace ) { if( 0 == dataSpace.Length ) throw new ArgumentException( SR.Get(SRID.DataSpaceLabelInvalidEmpty)); dataSpaceManager = parentStorage.Root.GetDataSpaceManager(); if( !dataSpaceManager.DataSpaceIsDefined( dataSpace ) ) throw new ArgumentException( SR.Get(SRID.DataSpaceLabelUndefined)); } openFileAccess = access; // becasue of the stream caching mechanism we must adjust FileAccess parameter. // We want to open stream with the widest access posible, in case Package was open in ReadWrite // we need to open stream in ReadWrite even if user explicitly asked us to do ReadOnly/WriteOnly. // There is a possibility of a next request coming in as as ReadWrite request, and we would like to // take advanatage of the cached stream by wrapping with appropriate access limitations. if (parentStorage.Root.OpenAccess == FileAccess.ReadWrite) { access = FileAccess.ReadWrite; } // Generate the access flags from the access parameter SafeNativeCompoundFileMethods.UpdateModeFlagFromFileAccess( access, ref grfMode ); // Only SHARE_EXCLUSIVE for now, FileShare issue TBD grfMode |= SafeNativeCompoundFileConstants.STGM_SHARE_EXCLUSIVE; CheckAccessMode(grfMode); // Act based on FileMode switch(mode) { case FileMode.Create: // Close down any existing streams floating out there if (null != core.exposedStream) { ((Stream)(core.exposedStream)).Close(); } core.exposedStream = null; if( null != core.safeIStream ) { // Release reference ((IDisposable) core.safeIStream).Dispose(); core.safeIStream = null; } // Cleanup done, create new stream in its place. grfMode |= SafeNativeCompoundFileConstants.STGM_CREATE; createdSafeIStream = CreateStreamOnParentIStorage( core.streamName, grfMode ); break; case FileMode.CreateNew: // If we've created a CFStream, this fails because stream is already there. if( null != core.safeIStream ) throw new IOException( SR.Get(SRID.StreamAlreadyExist)); // Need to call Create API with NULL create flags createdSafeIStream = CreateStreamOnParentIStorage( core.streamName, grfMode ); break; case FileMode.Append: // None of these are valid in a Create case FileMode.Open: case FileMode.OpenOrCreate: case FileMode.Truncate: default: throw new ArgumentException( SR.Get(SRID.FileModeInvalid)); } core.safeIStream = createdSafeIStream; // At this point we passed all previous checks and got the underlying IStream. // Set our data space label to the given label, and the stream to the retrieved stream. core.dataSpaceLabel = dataSpace; if( null != dataSpace ) { dataSpaceManager.CreateDataSpaceMapping( new CompoundFileStreamReference( parentStorage.FullNameInternal, core.streamName ), core.dataSpaceLabel ); } Stream returnStream = BuildStreamOnUnderlyingIStream( core.safeIStream, openFileAccess, this ); _needToGetTransformInfo = false; // We created stream with the given dataspace setting // so, there is no need to get the dataspace setting core.exposedStream = returnStream; return returnStream; } Stream BuildStreamOnUnderlyingIStream( IStream underlyingIStream, FileAccess access, StreamInfo parent ) { Stream rawStream = new CFStream( underlyingIStream, access, parent ); if( null == core.dataSpaceLabel ) { // The stream is not transformed in any data space, add buffering and return return new BufferedStream( rawStream ); } else { // Pass raw stream to data space manager to get real stream return parentStorage.Root.GetDataSpaceManager().CreateDataSpaceStream( StreamReference, rawStream); } } ////// A check against FileAccess.Read at create time. It should fail if /// the root container is read-only, or if we're pointlessly trying /// to create a read-only stream. /// void CreateTimeReadOnlyCheck( FileAccess access ) { // Can't create a stream if the root container is read-only if( FileAccess.Read == parentStorage.Root.OpenAccess ) throw new IOException( SR.Get(SRID.CanNotCreateInReadOnly)); // Doesn't make sense to create a new stream just to make it read-only if( access == FileAccess.Read ) throw new ArgumentException( SR.Get(SRID.CanNotCreateAsReadOnly)); } ////// Shortcut macro - calls the IStorage::CreateStream method on the parent /// storage object. /// IStream CreateStreamOnParentIStorage( string name, int mode ) { IStream createdStream = null; int nativeCallErrorCode = 0; if( !parentStorage.Exists ) { parentStorage.Create(); } nativeCallErrorCode = parentStorage.SafeIStorage.CreateStream( name, mode, 0, 0, out createdStream ); if( SafeNativeCompoundFileConstants.STG_E_INVALIDFLAG == nativeCallErrorCode ) { throw new ArgumentException( SR.Get(SRID.StorageFlagsUnsupported)); } else if ( SafeNativeCompoundFileConstants.S_OK != nativeCallErrorCode ) { throw new IOException( SR.Get(SRID.UnableToCreateStream), new COMException( SR.Get(SRID.NamedAPIFailure, "IStorage.CreateStream"), nativeCallErrorCode )); } // Parent storage has changed - invalidate all standing enuemrators parentStorage.InvalidateEnumerators(); return createdStream; } ////// Shortcut macro - calls the IStorage::OpenStream method on the parent /// storage object. /// IStream OpenStreamOnParentIStorage( string name, int mode ) { IStream openedStream = null; int nativeCallErrorCode = 0; nativeCallErrorCode = parentStorage.SafeIStorage.OpenStream( name, 0, mode, 0, out openedStream ); if( SafeNativeCompoundFileConstants.S_OK != nativeCallErrorCode ) { throw new IOException( SR.Get(SRID.UnableToOpenStream), new COMException( SR.Get(SRID.NamedAPIFailure, "IStorage.OpenStream"), nativeCallErrorCode )); } return openedStream; } ////// Deletes the stream specified by this StreamInfo /// internal void Delete() { CheckDisposedStatus(); if( InternalExists() ) { if( null != core.safeIStream ) { // Close out existing stream ((IDisposable) core.safeIStream).Dispose(); core.safeIStream = null; } parentStorage.DestroyElement( core.streamName ); // Parent storage has changed - invalidate all standing enuemrators parentStorage.InvalidateEnumerators(); } else { // If a FileInfo is told to delete a file that does not // exist, nothing happens. We follow that example here. } } ////// It is valid to have a StreamInfo class that points to a stream /// that does not (yet) exist. However, it is impossible to perform /// operations on a stream that does not exst, so the methods that /// require an existing stream need to be able to check if the stream /// exists before trying to perform its operations. /// ///Whether "this" stream exists internal bool InternalExists() { // If we have a stream, it's pretty obvious that we exist. if( null != core.safeIStream ) return true; // If parent storage does not exist, we can't possibly exist either if( !parentStorage.Exists ) return false; // At this point we know the parent storage exists, but we don't know // if we do. Try to open the stream. return SafeNativeCompoundFileConstants.S_OK == parentStorage.SafeIStorage.OpenStream( core.streamName, 0, SafeNativeCompoundFileConstants.STGM_READ | SafeNativeCompoundFileConstants.STGM_SHARE_EXCLUSIVE, 0, out core.safeIStream ); } ////// Most of the time internal methods that want to do an internal check /// to see if a stream exists is only interested in proceeding if it does. /// If it doesn't, abort with an exception. This implements the little /// shortcut. /// void VerifyExists() { if( !InternalExists() ) { throw new IOException( SR.Get(SRID.StreamNotExist)); } return; } // This fixes bug# 4947, a degenerate case of bug #5563 private Stream CFStreamOfClone( FileAccess access ) { long dummy = 0; IStream cloneStream = null; core.safeIStream.Clone( out cloneStream ); cloneStream.Seek( 0, SafeNativeCompoundFileConstants.STREAM_SEEK_SET, out dummy ); Stream returnStream = BuildStreamOnUnderlyingIStream( cloneStream, access, this ); core.exposedStream = returnStream; return returnStream; } // Check whether this StreamInfo object is still valid. If not, thrown an // ObjectDisposedException. internal void CheckDisposedStatus() { // Check to see if we're still valid. if( StreamInfoDisposed ) // Null name in core signifies the core object is disposed throw new ObjectDisposedException(null, SR.Get(SRID.StreamInfoDisposed)); } // Check whether this StreamInfo object is still valid. Return result. internal bool StreamInfoDisposed { get { // Check to see if we're still valid. // Null name in core signifies the core object is disposed. // Also check the parent storage. return (( null == core.streamName ) || parentStorage.StorageDisposed); } } // If we opened the IStream but haven't publicly exposed any Streams yet (i.e. InternalExists), // check to make sure the access modes match. internal void CheckAccessMode(int grfMode) { // Do we have an IStream? if( null != core.safeIStream ) { // Have we exposed it publicly yet? if( null == core.exposedStream ) { System.Runtime.InteropServices.ComTypes.STATSTG mySTATs; core.safeIStream.Stat( out mySTATs, SafeNativeCompoundFileConstants.STATFLAG_NONAME ); // Do the modes match? if( grfMode != mySTATs.grfMode ) { // Modes don't match, close out existing stream. ((IDisposable) core.safeIStream).Dispose(); core.safeIStream = null; } } } } internal CompoundFileStreamReference StreamReference { get { return _streamReference; } } // Inspect the transforms applied this stream and retreive the compression and // RM encryption options private void EnsureTransformInformation() { if (_needToGetTransformInfo && InternalExists()) { _encryptionOption = EncryptionOption.None; _compressionOption = CompressionOption.NotCompressed; //If the StreamInfo exists we go on to check if correct transform has been //applied to the Stream DataSpaceManager dsm = parentStorage.Root.GetDataSpaceManager(); Listtransforms = dsm.GetTransformsForStreamInfo(this); foreach (IDataTransform dataTransform in transforms) { string id = dataTransform.TransformIdentifier as string; if (id != null) { id = id.ToUpperInvariant(); if (String.CompareOrdinal(id, RightsManagementEncryptionTransform.ClassTransformIdentifier.ToUpperInvariant()) == 0 && (dataTransform as RightsManagementEncryptionTransform) != null) { _encryptionOption = EncryptionOption.RightsManagement; } else if (String.CompareOrdinal(id, CompressionTransform.ClassTransformIdentifier.ToUpperInvariant()) == 0 && (dataTransform as CompressionTransform) != null) { // We don't persist the compression level used during compression process // When we access the stream, all we can determine is whether it is compressed or not // In all our scenarios, the level we use is Level 9 which is equivalent to Maximum _compressionOption = CompressionOption.Maximum; } } } _needToGetTransformInfo = false; } } } } // 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
- WebServiceErrorEvent.cs
- DatePickerAutomationPeer.cs
- AmbientLight.cs
- SoapProtocolImporter.cs
- HttpClientCertificate.cs
- ReadOnlyAttribute.cs
- CompositeActivityDesigner.cs
- Memoizer.cs
- ControlDesigner.cs
- StringValueSerializer.cs
- GeometryValueSerializer.cs
- SynchronizedDisposablePool.cs
- PhonemeEventArgs.cs
- TypeResolver.cs
- ListItemCollection.cs
- RegularExpressionValidator.cs
- TextBounds.cs
- Section.cs
- datacache.cs
- KnownTypeHelper.cs
- ViewStateException.cs
- InputReportEventArgs.cs
- EntityDataSourceWrapperPropertyDescriptor.cs
- XmlSchemaRedefine.cs
- SqlParameter.cs
- XComponentModel.cs
- AttachedPropertyBrowsableWhenAttributePresentAttribute.cs
- _AutoWebProxyScriptWrapper.cs
- ApplySecurityAndSendAsyncResult.cs
- StrokeCollection2.cs
- EntityDataSourceWrapperPropertyDescriptor.cs
- DataTemplateKey.cs
- HttpProfileBase.cs
- WebPartTransformerAttribute.cs
- HttpWriter.cs
- NameTable.cs
- PropertySet.cs
- WebPartHeaderCloseVerb.cs
- FactoryGenerator.cs
- XamlGridLengthSerializer.cs
- DataGridViewCellPaintingEventArgs.cs
- HttpDictionary.cs
- HostedHttpContext.cs
- ScalarOps.cs
- ListenerAdapterBase.cs
- TemplateNameScope.cs
- WebBrowser.cs
- HtmlTableRow.cs
- DataGridViewImageColumn.cs
- QilInvoke.cs
- PingReply.cs
- Rule.cs
- RbTree.cs
- DataMemberConverter.cs
- XmlSerializerNamespaces.cs
- DocumentViewerConstants.cs
- SmiEventSink_Default.cs
- SpecularMaterial.cs
- ServerIdentity.cs
- PointIndependentAnimationStorage.cs
- AnnotationObservableCollection.cs
- Odbc32.cs
- TextParagraphCache.cs
- PaperSize.cs
- InvariantComparer.cs
- WindowsSolidBrush.cs
- FreezableOperations.cs
- TableRow.cs
- ComplusTypeValidator.cs
- ContainerSelectorBehavior.cs
- PostBackOptions.cs
- PerformanceCounterCategory.cs
- ApplicationInfo.cs
- SearchForVirtualItemEventArgs.cs
- TypeDescriptionProvider.cs
- Metadata.cs
- ReaderOutput.cs
- SecurityUniqueId.cs
- CodeAttributeDeclarationCollection.cs
- IHttpResponseInternal.cs
- newitemfactory.cs
- CharAnimationUsingKeyFrames.cs
- RangeValueProviderWrapper.cs
- HostedHttpContext.cs
- Validator.cs
- BitmapImage.cs
- DesignTimeHTMLTextWriter.cs
- SynchronizationValidator.cs
- CompiledELinqQueryState.cs
- BamlLocalizer.cs
- BoundColumn.cs
- LookupBindingPropertiesAttribute.cs
- FillBehavior.cs
- SqlProviderManifest.cs
- XsltCompileContext.cs
- DateTimeValueSerializerContext.cs
- ImageButton.cs
- _ShellExpression.cs
- Propagator.JoinPropagator.cs
- QilDataSource.cs