Code:
/ DotNET / DotNET / 8.0 / untmp / WIN_WINDOWS / lh_tools_devdiv_wpf / Windows / wcp / Shared / MS / Internal / IO / Packaging / PackagingUtilities.cs / 1 / 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
- CollectionBase.cs
- ImageInfo.cs
- EasingKeyFrames.cs
- DocumentCollection.cs
- HttpTransportBindingElement.cs
- Timeline.cs
- DataServiceQueryOfT.cs
- SystemDropShadowChrome.cs
- OleDbFactory.cs
- SecurityDescriptor.cs
- DataSourceControl.cs
- TextRange.cs
- ReadOnlyCollection.cs
- TabControlEvent.cs
- ProfileBuildProvider.cs
- GuidelineSet.cs
- ImageFormat.cs
- SecurityPolicySection.cs
- X509ChainPolicy.cs
- Utils.cs
- InternalConfigHost.cs
- TreeNodeConverter.cs
- EntityDataSourceViewSchema.cs
- Listen.cs
- DataTemplateKey.cs
- DataGridViewButtonCell.cs
- Formatter.cs
- Geometry3D.cs
- NamespaceDecl.cs
- ResourceType.cs
- UserMapPath.cs
- DataGridCellClipboardEventArgs.cs
- FileUtil.cs
- EventSinkActivityDesigner.cs
- CompositeControl.cs
- DirectionalLight.cs
- SRGSCompiler.cs
- coordinatorfactory.cs
- InstalledFontCollection.cs
- Win32.cs
- ThaiBuddhistCalendar.cs
- KeyedPriorityQueue.cs
- PolyLineSegmentFigureLogic.cs
- AliasedSlot.cs
- Attributes.cs
- PerspectiveCamera.cs
- TableColumn.cs
- LinkButton.cs
- Application.cs
- XmlLoader.cs
- DataRecordObjectView.cs
- ProfilePropertyMetadata.cs
- ChannelProtectionRequirements.cs
- Int32Collection.cs
- StackSpiller.Temps.cs
- DataRowCollection.cs
- IndexedEnumerable.cs
- COM2ColorConverter.cs
- SecurityUtils.cs
- SchemaExporter.cs
- EntityContainerRelationshipSetEnd.cs
- HttpRuntimeSection.cs
- _SslStream.cs
- QueryOperatorEnumerator.cs
- Configuration.cs
- PagerSettings.cs
- SqlNamer.cs
- TextRange.cs
- HorizontalAlignConverter.cs
- LicFileLicenseProvider.cs
- DataSourceComponent.cs
- CodeMemberProperty.cs
- DocumentViewerBaseAutomationPeer.cs
- HwndStylusInputProvider.cs
- HwndSourceKeyboardInputSite.cs
- InteropAutomationProvider.cs
- GAC.cs
- WeakReferenceEnumerator.cs
- SqlProviderUtilities.cs
- Currency.cs
- RadioButtonStandardAdapter.cs
- StateChangeEvent.cs
- ToolboxItem.cs
- ProtocolProfile.cs
- DesignerGenericWebPart.cs
- GridEntryCollection.cs
- ZipIOCentralDirectoryDigitalSignature.cs
- ConnectionManagementElementCollection.cs
- HttpHeaderCollection.cs
- GraphicsContext.cs
- SoapException.cs
- PasswordRecoveryDesigner.cs
- UpDownEvent.cs
- MsmqBindingBase.cs
- ResXFileRef.cs
- TargetConverter.cs
- ScriptingProfileServiceSection.cs
- Converter.cs
- ListViewInsertionMark.cs
- EntitySetBaseCollection.cs