Code:
/ 4.0 / 4.0 / untmp / DEVDIV_TFS / Dev10 / Releases / RTMRel / wpf / src / Shared / MS / Internal / IO / Packaging / PackagingUtilities.cs / 1305600 / PackagingUtilities.cs
//---------------------------------------------------------------------------- // //// Copyright (C) Microsoft Corporation. All rights reserved. // // // Description: // // History: // 05/13/2004: [....] Creation // //--------------------------------------------------------------------------- using System; using System.IO; using System.IO.IsolatedStorage; using MS.Internal.WindowsBase; // FriendAccessAllowed using System.Xml; // For XmlReader using System.Diagnostics; // For Debug.Assert using System.Text; // For Encoding using System.Windows; // For Exception strings - SRID using System.Security; // for SecurityCritical using System.Security.Permissions; // for permissions using Microsoft.Win32; // for Registry classes using MS.Internal; namespace MS.Internal.IO.Packaging { [FriendAccessAllowed] // Built into Base, used by Framework and Core internal static class PackagingUtilities { //----------------------------------------------------- // // Internal Fields // //----------------------------------------------------- internal static readonly string RelationshipNamespaceUri = "http://schemas.openxmlformats.org/package/2006/relationships"; internal static readonly ContentType RelationshipPartContentType = new ContentType("application/vnd.openxmlformats-package.relationships+xml"); internal const string ContainerFileExtension = "xps"; internal const string XamlFileExtension = "xaml"; //------------------------------------------------------ // // Internal Properties // //----------------------------------------------------- //------------------------------------------------------ // // Internal Methods // //------------------------------------------------------ #region Internal Methods ////// This method is used to determine if we support a given Encoding as per the /// OPC and XPS specs. Currently the only two encodings supported are UTF-8 and /// UTF-16 (Little Endian and Big Endian) /// /// XmlTextReader ///throws an exception if the encoding is not UTF-8 or UTF-16 internal static void PerformInitailReadAndVerifyEncoding(XmlTextReader reader) { Invariant.Assert(reader != null && reader.ReadState == ReadState.Initial); //If the first node is XmlDeclaration we check to see if the encoding attribute is present if (reader.Read() && reader.NodeType == XmlNodeType.XmlDeclaration && reader.Depth == 0) { string encoding; encoding = reader.GetAttribute(_encodingAttribute); if (encoding != null && encoding.Length > 0) { encoding = encoding.ToUpperInvariant(); //If a non-empty encoding attribute is present [for example - ] //we check to see if the value is either "utf-8" or utf-16. Only these two values are supported //Note: For Byte order markings that require additional information to be specified in //the encoding attribute in XmlDeclaration have already been ruled out by this check as we allow for //only two valid values. if (String.CompareOrdinal(encoding, _webNameUTF8) == 0 || String.CompareOrdinal(encoding, _webNameUnicode) == 0) return; else //if the encoding attribute has any other value we throw an exception throw new FileFormatException(SR.Get(SRID.EncodingNotSupported)); } } //if the XmlDeclaration is not present, or encoding attribute is not present, we //base our decision on byte order marking. reader.Encoding will take that into account //and return the correct value. //Note: For Byte order markings that require additional information to be specified in //the encoding attribute in XmlDeclaration have already been ruled out by the check above. //Note: If not encoding attribute is present or no byte order marking is present the //encoding default to UTF8 if (!(reader.Encoding is UnicodeEncoding || reader.Encoding is UTF8Encoding)) throw new FileFormatException(SR.Get(SRID.EncodingNotSupported)); } ////// VerifyStreamReadArgs /// /// stream /// buffer /// offset /// count ///Common argument verification for Stream.Read() static internal void VerifyStreamReadArgs(Stream s, byte[] buffer, int offset, int count) { if (!s.CanRead) throw new NotSupportedException(SR.Get(SRID.ReadNotSupported)); if (buffer == null) { throw new ArgumentNullException("buffer"); } if (offset < 0) { throw new ArgumentOutOfRangeException("offset", SR.Get(SRID.OffsetNegative)); } if (count < 0) { throw new ArgumentOutOfRangeException("count", SR.Get(SRID.ReadCountNegative)); } checked // catch any integer overflows { if (offset + count > buffer.Length) { throw new ArgumentException(SR.Get(SRID.ReadBufferTooSmall), "buffer"); } } } ////// VerifyStreamWriteArgs /// /// /// /// /// ///common argument verification for Stream.Write static internal void VerifyStreamWriteArgs(Stream s, byte[] buffer, int offset, int count) { if (!s.CanWrite) throw new NotSupportedException(SR.Get(SRID.WriteNotSupported)); if (buffer == null) { throw new ArgumentNullException("buffer"); } if (offset < 0) { throw new ArgumentOutOfRangeException("offset", SR.Get(SRID.OffsetNegative)); } if (count < 0) { throw new ArgumentOutOfRangeException("count", SR.Get(SRID.WriteCountNegative)); } checked { if (offset + count > buffer.Length) throw new ArgumentException(SR.Get(SRID.WriteBufferTooSmall), "buffer"); } } ////// Read utility that is guaranteed to return the number of bytes requested /// if they are available. /// /// stream to read from /// buffer to read into /// offset in buffer to write to /// bytes to read ///bytes read ///Normal Stream.Read does not guarantee how many bytes it will /// return. This one does. internal static int ReliableRead(Stream stream, byte[] buffer, int offset, int count) { return ReliableRead(stream, buffer, offset, count, count); } ////// Read utility that is guaranteed to return the number of bytes requested /// if they are available. /// /// stream to read from /// buffer to read into /// offset in buffer to write to /// count of bytes that we would like to read (max read size to try) /// minimal count of bytes that we would like to read (min read size to achieve) ///bytes read ///Normal Stream.Read does not guarantee how many bytes it will /// return. This one does. internal static int ReliableRead(Stream stream, byte[] buffer, int offset, int requestedCount, int requiredCount) { Invariant.Assert(stream != null); Invariant.Assert(buffer != null); Invariant.Assert(buffer.Length > 0); Invariant.Assert(offset >= 0); Invariant.Assert(requestedCount >= 0); Invariant.Assert(requiredCount >= 0); Invariant.Assert(checked(offset + requestedCount <= buffer.Length)); Invariant.Assert(requiredCount <= requestedCount); // let's read the whole block into our buffer int totalBytesRead = 0; while (totalBytesRead < requiredCount) { int bytesRead = stream.Read(buffer, offset + totalBytesRead, requestedCount - totalBytesRead); if (bytesRead == 0) { break; } totalBytesRead += bytesRead; } return totalBytesRead; } ////// Read utility that is guaranteed to return the number of bytes requested /// if they are available. /// /// BinaryReader to read from /// buffer to read into /// offset in buffer to write to /// bytes to read ///bytes read ///Normal Stream.Read does not guarantee how many bytes it will /// return. This one does. internal static int ReliableRead(BinaryReader reader, byte[] buffer, int offset, int count) { return ReliableRead(reader, buffer, offset, count, count); } ////// Read utility that is guaranteed to return the number of bytes requested /// if they are available. /// /// BinaryReader to read from /// buffer to read into /// offset in buffer to write to /// count of bytes that we would like to read (max read size to try) /// minimal count of bytes that we would like to read (min read size to achieve) ///bytes read ///Normal Stream.Read does not guarantee how many bytes it will /// return. This one does. internal static int ReliableRead(BinaryReader reader, byte[] buffer, int offset, int requestedCount, int requiredCount) { Invariant.Assert(reader != null); Invariant.Assert(buffer != null); Invariant.Assert(buffer.Length > 0); Invariant.Assert(offset >= 0); Invariant.Assert(requestedCount >= 0); Invariant.Assert(requiredCount >= 0); Invariant.Assert(checked(offset + requestedCount <= buffer.Length)); Invariant.Assert(requiredCount <= requestedCount); // let's read the whole block into our buffer int totalBytesRead = 0; while (totalBytesRead < requiredCount) { int bytesRead = reader.Read(buffer, offset + totalBytesRead, requestedCount - totalBytesRead); if (bytesRead == 0) { break; } totalBytesRead += bytesRead; } return totalBytesRead; } ////// CopyStream utility that is guaranteed to return the number of bytes copied (may be less then requested, /// if source stream doesn't have enough data) /// /// stream to read from /// stream to write to /// number of bytes to be copied(use Int64.MaxValue if the whole stream needs to be copied) /// number of bytes to be copied (usually it is 4K for scenarios where we expect a lot of data /// like in SparseMemoryStream case it could be larger ///bytes copied (might be less than requested if source stream is too short ///Neither source nor target stream are seeked; it is up to the caller to make sure that their positions are properly set. /// Target stream isn't truncated even if it has more data past the area that was copied. internal static long CopyStream(Stream sourceStream, Stream targetStream, long bytesToCopy, int bufferSize) { Invariant.Assert(sourceStream != null); Invariant.Assert(targetStream != null); Invariant.Assert(bytesToCopy >= 0); Invariant.Assert(bufferSize > 0); byte[] buffer = new byte[bufferSize]; // let's read the whole block into our buffer long bytesLeftToCopy = bytesToCopy; while (bytesLeftToCopy > 0) { int bytesRead = sourceStream.Read(buffer, 0, (int)Math.Min(bytesLeftToCopy, (long)bufferSize)); if (bytesRead == 0) { targetStream.Flush(); return bytesToCopy - bytesLeftToCopy; } targetStream.Write(buffer, 0, bytesRead); bytesLeftToCopy -= bytesRead; } // It must not be negative Debug.Assert(bytesLeftToCopy == 0); targetStream.Flush(); return bytesToCopy; } ////// Create a User-Domain Scoped IsolatedStorage file (or Machine-Domain scoped file if current user has no profile) /// /// returns the created file name /// number of times to retry in case of name collision (legal values between 0 and 100) ///the created stream ///retryCount was exceeded ///This function locks on IsoStoreSyncRoot and is thread-safe internal static Stream CreateUserScopedIsolatedStorageFileStreamWithRandomName(int retryCount, out String fileName) { // negative is illegal and place an upper limit of 100 if (retryCount < 0 || retryCount > 100) throw new ArgumentOutOfRangeException("retryCount"); Stream s = null; fileName = null; // GetRandomFileName returns a very random name, but collisions are still possible so we // retry if we encounter one. while (true) { try { // This function returns a highly-random name in 8.3 format. fileName = Path.GetRandomFileName(); lock (IsoStoreSyncRoot) { s = GetDefaultIsolatedStorageFile().GetStream(fileName); } // if we get to here we have a success condition so we can safely exit break; } catch (IOException) { // assume it is a name collision and ignore if we have not exhausted our retry count if (--retryCount < 0) throw; } } return s; } ////// Calculate overlap between two blocks, returning the offset and length of the overlap /// /// /// /// /// /// /// internal static void CalculateOverlap(long block1Offset, long block1Size, long block2Offset, long block2Size, out long overlapBlockOffset, out long overlapBlockSize) { checked { overlapBlockOffset = Math.Max(block1Offset, block2Offset); overlapBlockSize = Math.Min(block1Offset + block1Size, block2Offset + block2Size) - overlapBlockOffset; if (overlapBlockSize <= 0) { overlapBlockSize = 0; } } } ////// This method returns the count of xml attributes other than: /// 1. xmlns="namespace" /// 2. xmlns:someprefix="namespace" /// Reader should be positioned at the Element whose attributes /// are to be counted. /// /// ///An integer indicating the number of non-xmlns attributes internal static int GetNonXmlnsAttributeCount(XmlReader reader) { Debug.Assert(reader != null, "xmlReader should not be null"); Debug.Assert(reader.NodeType == XmlNodeType.Element, "XmlReader should be positioned at an Element"); int readerCount = 0; //If true, reader moves to the attribute //If false, there are no more attributes (or none) //and in that case the position of the reader is unchanged. //First time through, since the reader will be positioned at an Element, //MoveToNextAttribute is the same as MoveToFirstAttribute. while (reader.MoveToNextAttribute()) { if (String.CompareOrdinal(reader.Name, XmlNamespace) != 0 && String.CompareOrdinal(reader.Prefix, XmlNamespace) != 0) readerCount++; } //re-position the reader to the element reader.MoveToElement(); return readerCount; } ////// Any usage of IsolatedStorage static properties should lock on this for thread-safety /// internal static Object IsoStoreSyncRoot { get { return _isoStoreSyncObject; } } #endregion Internal Methods //----------------------------------------------------- // // Private Methods // //------------------------------------------------------ ////// Delete file created using CreateUserScopedIsolatedStorageFileStreamWithRandomName() /// /// ///Correctly handles temp/isostore differences private static void DeleteIsolatedStorageFile(String fileName) { lock (IsoStoreSyncRoot) { GetDefaultIsolatedStorageFile().IsoFile.DeleteFile(fileName); } } ////// Returns the IsolatedStorageFile scoped to Assembly, Domain and User /// ///Callers must lock on IsoStoreSyncRoot before calling this for thread-safety. /// For example: /// /// lock (IsoStoreSyncRoot) /// { /// // do something with the returned IsolatedStorageFile /// PackagingUtilities.DefaultIsolatedStorageFile.DeleteFile(_isolatedStorageStreamFileName); /// } /// /// private static ReliableIsolatedStorageFileFolder GetDefaultIsolatedStorageFile() { // Cache and re-use the same object for multiple requests - resurrect if disposed if (_defaultFile == null || _defaultFile.IsDisposed()) { _defaultFile = new ReliableIsolatedStorageFileFolder(); } return _defaultFile; } ////// Determine if current user has a User Profile so we can determine the appropriate /// scope to use for IsolatedStorage functionality. /// ////// Critical - Asserts read registry permission... /// - Asserts ControlPrincipal to access current user identity /// TAS - only returns a bool /// [SecurityCritical, SecurityTreatAsSafe] private static bool UserHasProfile() { // Acquire permissions to read the one key we care about from the registry // Acquite permission to query the current user identity PermissionSet permissionSet = new PermissionSet(PermissionState.None); permissionSet.AddPermission(new SecurityPermission(SecurityPermissionFlag.ControlPrincipal)); permissionSet.AddPermission(new RegistryPermission(RegistryPermissionAccess.Read, _fullProfileListKeyName)); permissionSet.Assert(); bool userHasProfile = false; RegistryKey userProfileKey = null; try { // inspect registry and look for user profile via SID string userSid = System.Security.Principal.WindowsIdentity.GetCurrent().User.Value; userProfileKey = Registry.LocalMachine.OpenSubKey(_profileListKeyName + @"\" + userSid); userHasProfile = userProfileKey != null; } finally { if (userProfileKey != null) userProfileKey.Close(); CodeAccessPermission.RevertAssert(); } return userHasProfile; } //------------------------------------------------------ // // Private Classes // //------------------------------------------------------ ////// This class extends IsolatedStorageFileStream by adding a finalizer to ensure that /// the underlying file is deleted when the stream is closed. /// private class SafeIsolatedStorageFileStream : IsolatedStorageFileStream { //------------------------------------------------------ // // Internal Methods // //------------------------------------------------------ internal SafeIsolatedStorageFileStream( string path, FileMode mode, FileAccess access, FileShare share, ReliableIsolatedStorageFileFolder folder) : base(path, mode, access, share, folder.IsoFile) { if (path == null) throw new ArgumentNullException("path"); _path = path; _folder = folder; _folder.AddRef(); } //------------------------------------------------------ // // Protected Methods // //------------------------------------------------------ protected override void Dispose(bool disposing) { if (!_disposed) { if (disposing) { // Non-standard pattern - call base.Dispose() first. // This is required because the base class is a stream and we cannot // delete the underlying file storage before it has a chance to close // and release it. base.Dispose(disposing); if (_path != null) { PackagingUtilities.DeleteIsolatedStorageFile(_path); _path = null; } //Decrement the count of files _folder.DecRef(); _folder = null; GC.SuppressFinalize(this); } _disposed = true; } } //------------------------------------------------------ // // Private Fields // //------------------------------------------------------ private string _path; private ReliableIsolatedStorageFileFolder _folder; private bool _disposed; } ////// This class extends IsolatedStorageFileStream by adding a finalizer to ensure that /// the underlying file is deleted when the stream is closed. /// private class ReliableIsolatedStorageFileFolder : IDisposable { //------------------------------------------------------ // // Internal Properties // //------------------------------------------------------ internal IsolatedStorageFile IsoFile { get { CheckDisposed(); return _file; } } ////// Call this when a new file is created in the isoFolder /// internal void AddRef() { lock (IsoStoreSyncRoot) { CheckDisposed(); checked { ++_refCount; } } } ////// Call this when a new file is deleted from the isoFolder /// internal void DecRef() { lock (IsoStoreSyncRoot) { CheckDisposed(); checked { --_refCount; } if (_refCount <= 0) { Dispose(); } } } ////// Only used within a lock statement /// ///internal bool IsDisposed() { return _disposed; } //------------------------------------------------------ // // Internal Methods // //------------------------------------------------------ internal ReliableIsolatedStorageFileFolder() { _userHasProfile = UserHasProfile(); _file = GetCurrentStore(); } /// /// This triggers AddRef because SafeIsoStream does this in its constructor /// /// ///internal Stream GetStream(String fileName) { CheckDisposed(); // This constructor uses a scope that isolates by AppDomain and User // We cannot include Assembly scope because it prevents sharing between Base and Core dll's return new SafeIsolatedStorageFileStream( fileName, FileMode.Create, FileAccess.ReadWrite, FileShare.None, this); } /// /// IDisposable.Dispose() /// public void Dispose() { Dispose(true); } //------------------------------------------------------ // // Protected Methods // //------------------------------------------------------ protected virtual void Dispose(bool disposing) { try { // only lock if we are disposing if (disposing) { lock (IsoStoreSyncRoot) { if (!_disposed) { using (_file) { _file.Remove(); } _disposed = true; } _file = null; } GC.SuppressFinalize(this); } else { // We cannot rely on other managed objects in our finalizer // so we allocate a fresh object to help us delete our temp folder. using (IsolatedStorageFile file = GetCurrentStore()) { file.Remove(); } } } catch (IsolatedStorageException) { // IsolatedStorageException can be thrown if the files that are being deleted, are // currently in use. These files will not get cleaned up. } } //------------------------------------------------------ // // Private Methods // //------------------------------------------------------ ////// Call this sparingly as it allocates resources /// ///private IsolatedStorageFile GetCurrentStore() { if (_userHasProfile) { return IsolatedStorageFile.GetUserStoreForDomain(); } else { return IsolatedStorageFile.GetMachineStoreForDomain(); } } ~ReliableIsolatedStorageFileFolder() { Dispose(false); } void CheckDisposed() { if (_disposed) throw new ObjectDisposedException("ReliableIsolatedStorageFileFolder"); } //------------------------------------------------------ // // Private Fields // //------------------------------------------------------ private static IsolatedStorageFile _file; private static bool _userHasProfile; private int _refCount; // number of outstanding "streams" private bool _disposed; } //------------------------------------------------------ // // Private Fields // //------------------------------------------------------ /// /// Synchronize access to IsolatedStorage methods that can step on each-other /// ///See PS 1468964 for details. private static Object _isoStoreSyncObject = new Object(); private static ReliableIsolatedStorageFileFolder _defaultFile; private const string XmlNamespace = "xmlns"; private const string _encodingAttribute = "encoding"; private static readonly string _webNameUTF8 = Encoding.UTF8.WebName.ToUpperInvariant(); private static readonly string _webNameUnicode = Encoding.Unicode.WebName.ToUpperInvariant(); ////// ProfileListKeyName /// ////// _profileListKeyName must remain readonly for security reasons /// private const string _profileListKeyName = @"SOFTWARE\Microsoft\Windows NT\CurrentVersion\ProfileList"; private const string _fullProfileListKeyName = @"HKEY_LOCAL_MACHINE\" + _profileListKeyName; } } // 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
- HtmlElementEventArgs.cs
- MessageQueuePermissionEntryCollection.cs
- MultipleFilterMatchesException.cs
- ByteAnimation.cs
- AppSettingsReader.cs
- SiteMap.cs
- AttributedMetaModel.cs
- ExpressionCopier.cs
- SoapReflectionImporter.cs
- ObjectDataSourceChooseMethodsPanel.cs
- ItemsControlAutomationPeer.cs
- OrderByQueryOptionExpression.cs
- TemplatedAdorner.cs
- MediaElement.cs
- autovalidator.cs
- ElementFactory.cs
- XPathCompileException.cs
- CounterCreationDataCollection.cs
- DownloadProgressEventArgs.cs
- XmlChildEnumerator.cs
- _OSSOCK.cs
- Interlocked.cs
- OleAutBinder.cs
- Renderer.cs
- OutputBuffer.cs
- Nullable.cs
- MissingSatelliteAssemblyException.cs
- SessionStateModule.cs
- ControlCachePolicy.cs
- SqlTriggerContext.cs
- CodeConstructor.cs
- CompilerGlobalScopeAttribute.cs
- OperationResponse.cs
- ContainerFilterService.cs
- CodeEntryPointMethod.cs
- ServiceDescriptionSerializer.cs
- InfoCardBinaryReader.cs
- BamlCollectionHolder.cs
- TransportDefaults.cs
- HelpHtmlBuilder.cs
- IdentifierCollection.cs
- coordinatorfactory.cs
- UpdateEventArgs.cs
- MatchAllMessageFilter.cs
- CommandID.cs
- CreateUserWizardAutoFormat.cs
- Message.cs
- PointAnimation.cs
- IndicShape.cs
- DataKey.cs
- MediaPlayerState.cs
- DictionaryEntry.cs
- DispatcherHooks.cs
- ImportCatalogPart.cs
- OdbcFactory.cs
- PropertyValidationContext.cs
- HitTestDrawingContextWalker.cs
- MatrixTransform3D.cs
- SR.cs
- ColumnCollection.cs
- ConfigXmlComment.cs
- AccessKeyManager.cs
- Helper.cs
- CounterSampleCalculator.cs
- User.cs
- CodeDesigner.cs
- ComboBoxHelper.cs
- RegexCode.cs
- MouseEvent.cs
- ListBoxItemAutomationPeer.cs
- ScriptResourceAttribute.cs
- UnionCodeGroup.cs
- ByteViewer.cs
- GridViewRow.cs
- DocumentXPathNavigator.cs
- SettingsAttributeDictionary.cs
- WmfPlaceableFileHeader.cs
- XmlIlGenerator.cs
- TracedNativeMethods.cs
- SchemaMerger.cs
- FlowNode.cs
- Registration.cs
- MobileControlBuilder.cs
- WpfKnownMember.cs
- CursorInteropHelper.cs
- EmbossBitmapEffect.cs
- GlyphShapingProperties.cs
- HttpResponseMessageProperty.cs
- AccessorTable.cs
- InputScope.cs
- IDispatchConstantAttribute.cs
- ListViewUpdatedEventArgs.cs
- PerformanceCounter.cs
- XamlPointCollectionSerializer.cs
- Imaging.cs
- TreeNodeStyleCollection.cs
- SqlFunctionAttribute.cs
- ConsoleTraceListener.cs
- TextServicesProperty.cs
- ArcSegment.cs