The Labs \ Source Viewer \ SSCLI \ System.IO.IsolatedStorage \ IsolatedStorageFileStream

  1. // ==++==
  2. //
  3. //
  4. // Copyright (c) 2006 Microsoft Corporation. All rights reserved.
  5. //
  6. // The use and distribution terms for this software are contained in the file
  7. // named license.txt, which can be found in the root of this distribution.
  8. // By using this software in any fashion, you are agreeing to be bound by the
  9. // terms of this license.
  10. //
  11. // You must not remove this notice, or any other, from this software.
  12. //
  13. //
  14. // ==--==
  15. /*============================================================
  16. *
  17. * Class:  IsolatedStorageFileStream
  18. *
  19. *
  20. * Purpose: Provides access to files using the same interface as FileStream
  21. *
  22. * Date:  Feb 18, 2000
  23. *
  24. ===========================================================*/
  25. namespace System.IO.IsolatedStorage
  26. {
  27.     using System;
  28.     using System.IO;
  29.     using Microsoft.Win32;
  30.     using Microsoft.Win32.SafeHandles;
  31.     using System.Security;
  32.     using System.Security.Permissions;
  33.     using System.Threading;
  34.     using System.Runtime.InteropServices;
  35.     using System.Runtime.Versioning;
  36.    
  37.     [System.Runtime.InteropServices.ComVisible(true)]
  38.     public class IsolatedStorageFileStream : FileStream
  39.     {
  40.         private const int s_BlockSize = 1024;
  41.         // Should be a power of 2!
  42.         // see usage before
  43.         // changing this constant
  44.         // s_BackSlash is initialized in the contructor with Path.DirectorySeparatorChar
  45.         private readonly string s_BackSlash;
  46.        
  47.         private FileStream m_fs;
  48.         private IsolatedStorageFile m_isf;
  49.         private string m_GivenPath;
  50.         private string m_FullPath;
  51.         private bool m_OwnedStore;
  52.        
  53.         private IsolatedStorageFileStream()
  54.         {
  55.         }
  56.        
  57.         [ResourceExposure(ResourceScope.AppDomain | ResourceScope.Assembly)]
  58.         [ResourceConsumption(ResourceScope.Machine | ResourceScope.Assembly, ResourceScope.AppDomain | ResourceScope.Assembly)]
  59.         public IsolatedStorageFileStream(string path, FileMode mode) : this(path, mode, (mode == FileMode.Append ? FileAccess.Write : FileAccess.ReadWrite), FileShare.None, null)
  60.         {
  61.         }
  62.        
  63.         [ResourceExposure(ResourceScope.Machine | ResourceScope.Assembly)]
  64.         [ResourceConsumption(ResourceScope.Machine | ResourceScope.Assembly)]
  65.         public IsolatedStorageFileStream(string path, FileMode mode, IsolatedStorageFile isf) : this(path, mode, FileAccess.ReadWrite, FileShare.None, isf)
  66.         {
  67.         }
  68.        
  69.         [ResourceExposure(ResourceScope.AppDomain | ResourceScope.Assembly)]
  70.         [ResourceConsumption(ResourceScope.Machine | ResourceScope.Assembly, ResourceScope.AppDomain | ResourceScope.Assembly)]
  71.         public IsolatedStorageFileStream(string path, FileMode mode, FileAccess access) : this(path, mode, access, access == FileAccess.Read ? FileShare.Read : FileShare.None, DefaultBufferSize, null)
  72.         {
  73.         }
  74.        
  75.         [ResourceExposure(ResourceScope.Machine | ResourceScope.Assembly)]
  76.         [ResourceConsumption(ResourceScope.Machine | ResourceScope.Assembly)]
  77.         public IsolatedStorageFileStream(string path, FileMode mode, FileAccess access, IsolatedStorageFile isf) : this(path, mode, access, access == FileAccess.Read ? FileShare.Read : FileShare.None, DefaultBufferSize, isf)
  78.         {
  79.         }
  80.        
  81.         [ResourceExposure(ResourceScope.AppDomain | ResourceScope.Assembly)]
  82.         [ResourceConsumption(ResourceScope.Machine | ResourceScope.Assembly, ResourceScope.AppDomain | ResourceScope.Assembly)]
  83.         public IsolatedStorageFileStream(string path, FileMode mode, FileAccess access, FileShare share) : this(path, mode, access, share, DefaultBufferSize, null)
  84.         {
  85.         }
  86.        
  87.         [ResourceExposure(ResourceScope.Machine | ResourceScope.Assembly)]
  88.         [ResourceConsumption(ResourceScope.Machine | ResourceScope.Assembly)]
  89.         public IsolatedStorageFileStream(string path, FileMode mode, FileAccess access, FileShare share, IsolatedStorageFile isf) : this(path, mode, access, share, DefaultBufferSize, isf)
  90.         {
  91.         }
  92.        
  93.         [ResourceExposure(ResourceScope.AppDomain | ResourceScope.Assembly)]
  94.         [ResourceConsumption(ResourceScope.Machine | ResourceScope.Assembly, ResourceScope.AppDomain | ResourceScope.Assembly)]
  95.         public IsolatedStorageFileStream(string path, FileMode mode, FileAccess access, FileShare share, int bufferSize) : this(path, mode, access, share, bufferSize, null)
  96.         {
  97.         }
  98.        
  99.         // If the isolated storage file is null, then we default to using a file
  100.         // that is scoped by user, appdomain, and assembly.
  101.         [ResourceExposure(ResourceScope.Machine | ResourceScope.Assembly)]
  102.         [ResourceConsumption(ResourceScope.Machine | ResourceScope.Assembly)]
  103.         public IsolatedStorageFileStream(string path, FileMode mode, FileAccess access, FileShare share, int bufferSize, IsolatedStorageFile isf)
  104.         {
  105.             if (path == null)
  106.                 throw new ArgumentNullException("path");
  107.            
  108.             if (s_BackSlash == null)
  109.                 s_BackSlash = new string(System.IO.Path.DirectorySeparatorChar, 1);
  110.            
  111.             if ((path.Length == 0) || path.Equals(s_BackSlash))
  112.                 throw new ArgumentException(Environment.GetResourceString("IsolatedStorage_path"));
  113.            
  114.             ulong oldFileSize = 0;
  115.             ulong newFileSize;
  116.             bool fNewFile = false;
  117.             bool fLock = false;
  118.             FileInfo fOld;
  119.            
  120.             if (isf == null) {
  121.                 m_OwnedStore = true;
  122.                 isf = IsolatedStorageFile.GetUserStoreForDomain();
  123.             }
  124.            
  125.             m_isf = isf;
  126.            
  127.             FileIOPermission fiop = new FileIOPermission(FileIOPermissionAccess.AllAccess, m_isf.RootDirectory);
  128.            
  129.             fiop.Assert();
  130.             fiop.PermitOnly();
  131.            
  132.             m_GivenPath = path;
  133.             m_FullPath = m_isf.GetFullPath(m_GivenPath);
  134.            
  135.             try {
  136.                 // for finally Unlocking locked store
  137.                 // Cache the old file size if the file size could change
  138.                 // Also find if we are going to create a new file.
  139.                
  140.                 switch (mode) {
  141.                     case FileMode.CreateNew:
  142.                         // Assume new file
  143.                         fNewFile = true;
  144.                         break;
  145.                     case FileMode.Create:
  146.                     case FileMode.OpenOrCreate:
  147.                     case FileMode.Truncate:
  148.                     case FileMode.Append:
  149.                        
  150.                         // Check for New file & Unreserve
  151.                         // Check for new file
  152.                         // Unreserve old file size
  153.                         // Check for new file
  154.                         m_isf.Lock();
  155.                         // oldFileSize needs to be
  156.                         // protected
  157.                         fLock = true;
  158.                         // Lock succeded
  159.                         try {
  160.                             fOld = new FileInfo(m_FullPath);
  161.                             oldFileSize = IsolatedStorageFile.RoundToBlockSize((ulong)fOld.Length);
  162.                         }
  163.                         catch (FileNotFoundException) {
  164.                             fNewFile = true;
  165.                         }
  166.                         catch {
  167.                         }
  168.                        
  169.                         break;
  170.                     case FileMode.Open:
  171.                        
  172.                         // Open existing, else exception
  173.                         break;
  174.                     default:
  175.                        
  176.                         throw new ArgumentException(Environment.GetResourceString("IsolatedStorage_FileOpenMode"));
  177.                         break;
  178.                 }
  179.                
  180.                 if (fNewFile)
  181.                     m_isf.ReserveOneBlock();
  182.                
  183.                 try {
  184.                     m_fs = new FileStream(m_FullPath, mode, access, share, bufferSize, FileOptions.None, m_GivenPath, true);
  185.                 }
  186.                 catch {
  187.                    
  188.                     if (fNewFile)
  189.                         m_isf.UnreserveOneBlock();
  190.                    
  191.                     throw;
  192.                 }
  193.                
  194.                 // make adjustment to the Reserve / Unreserve state
  195.                
  196.                 if ((fNewFile == false) && ((mode == FileMode.Truncate) || (mode == FileMode.Create))) {
  197.                     newFileSize = IsolatedStorageFile.RoundToBlockSize((ulong)m_fs.Length);
  198.                    
  199.                     if (oldFileSize > newFileSize)
  200.                         m_isf.Unreserve(oldFileSize - newFileSize);
  201.                     else if (newFileSize > oldFileSize)
  202.                         // Can this happen ?
  203.                         m_isf.Reserve(newFileSize - oldFileSize);
  204.                 }
  205.                
  206.             }
  207.             finally {
  208.                 if (fLock)
  209.                     m_isf.Unlock();
  210.             }
  211.             CodeAccessPermission.RevertAll();
  212.            
  213.         }
  214.        
  215.        
  216.         public override bool CanRead {
  217.             get { return m_fs.CanRead; }
  218.         }
  219.        
  220.         public override bool CanWrite {
  221.             get { return m_fs.CanWrite; }
  222.         }
  223.        
  224.         public override bool CanSeek {
  225.             get { return m_fs.CanSeek; }
  226.         }
  227.        
  228.         public override bool IsAsync {
  229.             get { return m_fs.IsAsync; }
  230.         }
  231.        
  232.         public override long Length {
  233.             get { return m_fs.Length; }
  234.         }
  235.        
  236.         public override long Position {
  237.            
  238.             get { return m_fs.Position; }
  239.            
  240.             set {
  241.                 if (value < 0) {
  242.                     throw new ArgumentOutOfRangeException("value", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
  243.                 }
  244.                
  245.                 Seek(value, SeekOrigin.Begin);
  246.             }
  247.         }
  248.        
  249.        
  250.         protected override void Dispose(bool disposing)
  251.         {
  252.             if (disposing) {
  253.                 if (m_fs != null)
  254.                     m_fs.Close();
  255.                 if (m_OwnedStore && m_isf != null)
  256.                     m_isf.Close();
  257.             }
  258.             base.Dispose(disposing);
  259.         }
  260.        
  261.         public override void Flush()
  262.         {
  263.             m_fs.Flush();
  264.         }
  265.        
  266.         [Obsolete("This property has been deprecated. Please use IsolatedStorageFileStream's SafeFileHandle property instead. http://go.microsoft.com/fwlink/?linkid=14202")]
  267.         public override IntPtr Handle {
  268.             [SecurityPermissionAttribute(SecurityAction.LinkDemand, Flags = SecurityPermissionFlag.UnmanagedCode)]
  269.             [SecurityPermissionAttribute(SecurityAction.InheritanceDemand, Flags = SecurityPermissionFlag.UnmanagedCode)]
  270.             get {
  271.                 NotPermittedError();
  272.                 return Win32Native.INVALID_HANDLE_VALUE;
  273.             }
  274.         }
  275.        
  276.         public override SafeFileHandle SafeFileHandle {
  277.             [SecurityPermissionAttribute(SecurityAction.LinkDemand, Flags = SecurityPermissionFlag.UnmanagedCode)]
  278.             [SecurityPermissionAttribute(SecurityAction.InheritanceDemand, Flags = SecurityPermissionFlag.UnmanagedCode)]
  279.             get {
  280.                 NotPermittedError();
  281.                 return null;
  282.             }
  283.         }
  284.        
  285.         public override void SetLength(long value)
  286.         {
  287.             m_isf.Lock();
  288.             // oldLen needs to be protected
  289.             try {
  290.                 ulong oldLen = (ulong)m_fs.Length;
  291.                 ulong newLen = (ulong)value;
  292.                
  293.                 // Reserve before the operation.
  294.                 m_isf.Reserve(oldLen, newLen);
  295.                
  296.                 try {
  297.                    
  298.                     ZeroInit(oldLen, newLen);
  299.                    
  300.                     m_fs.SetLength(value);
  301.                    
  302.                 }
  303.                 catch {
  304.                    
  305.                     // Undo the reserve
  306.                     m_isf.UndoReserveOperation(oldLen, newLen);
  307.                    
  308.                     throw;
  309.                 }
  310.                
  311.                 // Unreserve if this operation reduced the file size.
  312.                 if (oldLen > newLen) {
  313.                     // params oldlen, newlength reversed on purpose.
  314.                     m_isf.UndoReserveOperation(newLen, oldLen);
  315.                 }
  316.                
  317.             }
  318.             finally {
  319.                 m_isf.Unlock();
  320.             }
  321.         }
  322.        
  323.         // 0 out the allocated disk so that
  324.         // untrusted apps won't be able to read garbage, which
  325.         // is a security hole, if allowed.
  326.         // This may not be necessary in some file systems ?
  327.         private void ZeroInit(ulong oldLen, ulong newLen)
  328.         {
  329.             if (oldLen >= newLen)
  330.                 return;
  331.            
  332.             ulong rem = newLen - oldLen;
  333.             byte[] buffer = new byte[s_BlockSize];
  334.             // buffer is zero inited
  335.             // here by the runtime
  336.             // memory allocator.
  337.             // back up the current position.
  338.             long pos = m_fs.Position;
  339.            
  340.             m_fs.Seek((long)oldLen, SeekOrigin.Begin);
  341.            
  342.             // If we have a small number of bytes to write, do that and
  343.             // we are done.
  344.             if (rem <= (ulong)s_BlockSize) {
  345.                 m_fs.Write(buffer, 0, (int)rem);
  346.                 m_fs.Position = pos;
  347.                 return;
  348.             }
  349.            
  350.             // Block write is better than writing a byte in a loop
  351.             // or all bytes. The number of bytes to write could
  352.             // be very large.
  353.            
  354.             // Align to block size
  355.             // allign = s_BlockSize - (int)(oldLen % s_BlockSize);
  356.             // Converting % to & operation since s_BlockSize is a power of 2
  357.            
  358.             int allign = s_BlockSize - (int)(oldLen & ((ulong)s_BlockSize - 1));
  359.            
  360.             /*
  361.                 this will never happen since we already handled this case
  362.                 leaving this code here for documentation
  363.             if ((ulong)allign > rem)
  364.                 allign = (int)rem;
  365.             */           
  366.            
  367. m_fs.Write(buffer, 0, allign);
  368.             rem -= (ulong)allign;
  369.            
  370.             int nBlocks = (int)(rem / s_BlockSize);
  371.            
  372.             // Write out one block at a time.
  373.             for (int i = 0; i < nBlocks; ++i)
  374.                 m_fs.Write(buffer, 0, s_BlockSize);
  375.            
  376.             // Write out the remaining bytes.
  377.             // m_fs.Write(buffer, 0, (int) (rem % s_BlockSize));
  378.             // Converting % to & operation since s_BlockSize is a power of 2
  379.             m_fs.Write(buffer, 0, (int)(rem & ((ulong)s_BlockSize - 1)));
  380.            
  381.             // restore the current position
  382.             m_fs.Position = pos;
  383.         }
  384.        
  385.         public override int Read(byte[] buffer, int offset, int count)
  386.         {
  387.             return m_fs.Read(buffer, offset, count);
  388.         }
  389.        
  390.         public override int ReadByte()
  391.         {
  392.             return m_fs.ReadByte();
  393.         }
  394.        
  395.         public override long Seek(long offset, SeekOrigin origin)
  396.         {
  397.             long ret;
  398.            
  399.             m_isf.Lock();
  400.             // oldLen needs to be protected
  401.             try {
  402.                
  403.                 // Seek operation could increase the file size, make sure
  404.                 // that the quota is updated, and file is zeroed out
  405.                
  406.                 ulong oldLen;
  407.                 ulong newLen;
  408.                 oldLen = (ulong)m_fs.Length;
  409.                
  410.                 switch (origin) {
  411.                     case SeekOrigin.Begin:
  412.                         newLen = (ulong)offset;
  413.                         break;
  414.                     case SeekOrigin.Current:
  415.                         newLen = (ulong)(m_fs.Position + offset);
  416.                         break;
  417.                     case SeekOrigin.End:
  418.                         newLen = oldLen + (ulong)offset;
  419.                         break;
  420.                     default:
  421.                         throw new ArgumentException(Environment.GetResourceString("IsolatedStorage_SeekOrigin"));
  422.                         break;
  423.                 }
  424.                
  425.                 m_isf.Reserve(oldLen, newLen);
  426.                
  427.                 try {
  428.                    
  429.                     ZeroInit(oldLen, newLen);
  430.                    
  431.                     ret = m_fs.Seek(offset, origin);
  432.                    
  433.                 }
  434.                 catch {
  435.                    
  436.                     m_isf.UndoReserveOperation(oldLen, newLen);
  437.                    
  438.                     throw;
  439.                 }
  440.             }
  441.             finally {
  442.                 m_isf.Unlock();
  443.             }
  444.            
  445.             return ret;
  446.         }
  447.        
  448.         public override void Write(byte[] buffer, int offset, int count)
  449.         {
  450.             m_isf.Lock();
  451.             // oldLen needs to be protected
  452.             try {
  453.                
  454.                 ulong oldLen = (ulong)m_fs.Length;
  455.                 ulong newLen = (ulong)(m_fs.Position + count);
  456.                
  457.                 m_isf.Reserve(oldLen, newLen);
  458.                
  459.                 try {
  460.                    
  461.                     m_fs.Write(buffer, offset, count);
  462.                    
  463.                 }
  464.                 catch {
  465.                    
  466.                     m_isf.UndoReserveOperation(oldLen, newLen);
  467.                    
  468.                     throw;
  469.                 }
  470.             }
  471.             finally {
  472.                 m_isf.Unlock();
  473.             }
  474.         }
  475.        
  476.         public override void WriteByte(byte value)
  477.         {
  478.             m_isf.Lock();
  479.             // oldLen needs to be protected
  480.             try {
  481.                 ulong oldLen = (ulong)m_fs.Length;
  482.                 ulong newLen = (ulong)m_fs.Position + 1;
  483.                
  484.                 m_isf.Reserve(oldLen, newLen);
  485.                
  486.                 try {
  487.                    
  488.                     m_fs.WriteByte(value);
  489.                    
  490.                 }
  491.                 catch {
  492.                    
  493.                     m_isf.UndoReserveOperation(oldLen, newLen);
  494.                    
  495.                     throw;
  496.                 }
  497.             }
  498.             finally {
  499.                 m_isf.Unlock();
  500.             }
  501.         }
  502.        
  503.         [HostProtection(ExternalThreading = true)]
  504.         public override IAsyncResult BeginRead(byte[] buffer, int offset, int numBytes, AsyncCallback userCallback, object stateObject)
  505.         {
  506.             return m_fs.BeginRead(buffer, offset, numBytes, userCallback, stateObject);
  507.         }
  508.        
  509.         public override int EndRead(IAsyncResult asyncResult)
  510.         {
  511.             // try-catch to avoid leaking path info
  512.             return m_fs.EndRead(asyncResult);
  513.            
  514.         }
  515.        
  516.         [HostProtection(ExternalThreading = true)]
  517.         public override IAsyncResult BeginWrite(byte[] buffer, int offset, int numBytes, AsyncCallback userCallback, object stateObject)
  518.         {
  519.            
  520.             m_isf.Lock();
  521.             // oldLen needs to be protected
  522.             try {
  523.                
  524.                 ulong oldLen = (ulong)m_fs.Length;
  525.                 ulong newLen = (ulong)m_fs.Position + (ulong)numBytes;
  526.                 m_isf.Reserve(oldLen, newLen);
  527.                
  528.                 try {
  529.                    
  530.                     return m_fs.BeginWrite(buffer, offset, numBytes, userCallback, stateObject);
  531.                    
  532.                 }
  533.                 catch {
  534.                    
  535.                     m_isf.UndoReserveOperation(oldLen, newLen);
  536.                    
  537.                     throw;
  538.                 }
  539.             }
  540.             finally {
  541.                 m_isf.Unlock();
  542.             }
  543.         }
  544.        
  545.         public override void EndWrite(IAsyncResult asyncResult)
  546.         {
  547.             m_fs.EndWrite(asyncResult);
  548.         }
  549.        
  550.         internal void NotPermittedError(string str)
  551.         {
  552.             throw new IsolatedStorageException(str);
  553.         }
  554.        
  555.         internal void NotPermittedError()
  556.         {
  557.             NotPermittedError(Environment.GetResourceString("IsolatedStorage_Operation"));
  558.         }
  559.        
  560.     }
  561. }

Developer Fusion