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

  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:  IsolatedStorageFile
  18. *
  19. *
  20. * Purpose: Provides access to Application files and folders
  21. *
  22. * Date:  Feb 18, 2000
  23. *
  24. ===========================================================*/
  25. namespace System.IO.IsolatedStorage
  26. {
  27.     using System;
  28.     using System.Text;
  29.     using System.IO;
  30.     using Microsoft.Win32;
  31.     using Microsoft.Win32.SafeHandles;
  32.     using System.Collections;
  33.     using System.Security;
  34.     using System.Threading;
  35.     using System.Security.Policy;
  36.     using System.Security.Permissions;
  37.     using System.Security.Cryptography;
  38.     using System.Runtime.InteropServices;
  39.     using System.Runtime.CompilerServices;
  40.     using System.Runtime.Versioning;
  41.     using System.Globalization;
  42.    
  43.     [System.Runtime.InteropServices.ComVisible(true)]
  44.     public sealed class IsolatedStorageFile : IsolatedStorage, IDisposable
  45.     {
  46.         private const int s_BlockSize = 1024;
  47.         private const int s_DirSize = s_BlockSize;
  48.         private const string s_name = "file.store";
  49.         internal const string s_Files = "Files";
  50.         internal const string s_AssemFiles = "AssemFiles";
  51.         internal const string s_AppFiles = "AppFiles";
  52.         internal const string s_IDFile = "identity.dat";
  53.         internal const string s_InfoFile = "info.dat";
  54.         internal const string s_AppInfoFile = "appinfo.dat";
  55.        
  56.         private static string s_RootDirUser;
  57.         private static string s_RootDirMachine;
  58.         private static string s_RootDirRoaming;
  59.         private static string s_appDataDir;
  60.        
  61.         private static FileIOPermission s_PermUser;
  62.         private static FileIOPermission s_PermMachine;
  63.         private static FileIOPermission s_PermRoaming;
  64.         private static IsolatedStorageFilePermission s_PermAdminUser;
  65.        
  66.         private FileIOPermission m_fiop;
  67.         private string m_RootDir;
  68.         private string m_InfoFile;
  69.         private string m_SyncObjectName;
  70.         private IntPtr m_handle;
  71.         private bool m_closed;
  72.         private bool m_bDisposed = false;
  73.        
  74.         #if _DEBUG
  75.         private static bool s_fDebug;
  76.         #endif
  77.        
  78.         internal IsolatedStorageFile()
  79.         {
  80.         }
  81.        
  82.         [ResourceExposure(ResourceScope.AppDomain | ResourceScope.Assembly)]
  83.         [ResourceConsumption(ResourceScope.Machine | ResourceScope.Assembly, ResourceScope.AppDomain | ResourceScope.Assembly)]
  84.         public static IsolatedStorageFile GetUserStoreForDomain()
  85.         {
  86.             return GetStore(IsolatedStorageScope.Assembly | IsolatedStorageScope.Domain | IsolatedStorageScope.User, null, null);
  87.         }
  88.        
  89.         [ResourceExposure(ResourceScope.Machine | ResourceScope.Assembly)]
  90.         [ResourceConsumption(ResourceScope.Machine | ResourceScope.Assembly, ResourceScope.Machine | ResourceScope.Assembly)]
  91.         public static IsolatedStorageFile GetUserStoreForAssembly()
  92.         {
  93.             return GetStore(IsolatedStorageScope.Assembly | IsolatedStorageScope.User, null, null);
  94.         }
  95.        
  96.         [ResourceExposure(ResourceScope.Machine | ResourceScope.Assembly)]
  97.         [ResourceConsumption(ResourceScope.Machine | ResourceScope.Assembly, ResourceScope.Machine | ResourceScope.Assembly)]
  98.         public static IsolatedStorageFile GetUserStoreForApplication()
  99.         {
  100.             return GetStore(IsolatedStorageScope.Application | IsolatedStorageScope.User, null);
  101.         }
  102.        
  103.         [ResourceExposure(ResourceScope.AppDomain | ResourceScope.Assembly)]
  104.         [ResourceConsumption(ResourceScope.Machine | ResourceScope.Assembly, ResourceScope.AppDomain | ResourceScope.Assembly)]
  105.         public static IsolatedStorageFile GetMachineStoreForDomain()
  106.         {
  107.             return GetStore(IsolatedStorageScope.Assembly | IsolatedStorageScope.Domain | IsolatedStorageScope.Machine, null, null);
  108.         }
  109.        
  110.         [ResourceExposure(ResourceScope.Machine | ResourceScope.Assembly)]
  111.         [ResourceConsumption(ResourceScope.Machine | ResourceScope.Assembly, ResourceScope.Machine | ResourceScope.Assembly)]
  112.         public static IsolatedStorageFile GetMachineStoreForAssembly()
  113.         {
  114.             return GetStore(IsolatedStorageScope.Assembly | IsolatedStorageScope.Machine, null, null);
  115.         }
  116.        
  117.         [ResourceExposure(ResourceScope.Machine | ResourceScope.Assembly)]
  118.         [ResourceConsumption(ResourceScope.Machine | ResourceScope.Assembly, ResourceScope.Machine | ResourceScope.Assembly)]
  119.         public static IsolatedStorageFile GetMachineStoreForApplication()
  120.         {
  121.             return GetStore(IsolatedStorageScope.Application | IsolatedStorageScope.Machine, null);
  122.         }
  123.        
  124.         [ResourceExposure(ResourceScope.Machine | ResourceScope.Assembly)]
  125.         [ResourceConsumption(ResourceScope.Machine | ResourceScope.Assembly)]
  126.         public static IsolatedStorageFile GetStore(IsolatedStorageScope scope, Type domainEvidenceType, Type assemblyEvidenceType)
  127.         {
  128.             if (domainEvidenceType != null)
  129.                 DemandAdminPermission();
  130.            
  131.             IsolatedStorageFile sf = new IsolatedStorageFile();
  132.             sf.InitStore(scope, domainEvidenceType, assemblyEvidenceType);
  133.             sf.Init(scope);
  134.             return sf;
  135.         }
  136.        
  137.         [ResourceExposure(ResourceScope.Machine | ResourceScope.Assembly)]
  138.         [ResourceConsumption(ResourceScope.Machine | ResourceScope.Assembly)]
  139.         public static IsolatedStorageFile GetStore(IsolatedStorageScope scope, object domainIdentity, object assemblyIdentity)
  140.         {
  141.             // Verify input params.
  142.             if (IsDomain(scope) && (domainIdentity == null))
  143.                 throw new ArgumentNullException("domainIdentity");
  144.            
  145.             if (assemblyIdentity == null)
  146.                 throw new ArgumentNullException("assemblyIdentity");
  147.            
  148.             DemandAdminPermission();
  149.            
  150.             IsolatedStorageFile sf = new IsolatedStorageFile();
  151.             sf.InitStore(scope, domainIdentity, assemblyIdentity, null);
  152.             sf.Init(scope);
  153.            
  154.             return sf;
  155.         }
  156.        
  157.         [ResourceExposure(ResourceScope.Machine | ResourceScope.Assembly)]
  158.         [ResourceConsumption(ResourceScope.Machine | ResourceScope.Assembly)]
  159.         public static IsolatedStorageFile GetStore(IsolatedStorageScope scope, Evidence domainEvidence, Type domainEvidenceType, Evidence assemblyEvidence, Type assemblyEvidenceType)
  160.         {
  161.             // Verify input params.
  162.             if (IsDomain(scope) && (domainEvidence == null))
  163.                 throw new ArgumentNullException("domainEvidence");
  164.            
  165.             if (assemblyEvidence == null)
  166.                 throw new ArgumentNullException("assemblyEvidence");
  167.            
  168.             DemandAdminPermission();
  169.            
  170.             IsolatedStorageFile sf = new IsolatedStorageFile();
  171.             sf.InitStore(scope, domainEvidence, domainEvidenceType, assemblyEvidence, assemblyEvidenceType, null, null);
  172.             sf.Init(scope);
  173.            
  174.             return sf;
  175.         }
  176.        
  177.         [ResourceExposure(ResourceScope.Machine | ResourceScope.Assembly)]
  178.         [ResourceConsumption(ResourceScope.Machine | ResourceScope.Assembly)]
  179.         public static IsolatedStorageFile GetStore(IsolatedStorageScope scope, Type applicationEvidenceType)
  180.         {
  181.             if (applicationEvidenceType != null)
  182.                 DemandAdminPermission();
  183.            
  184.             IsolatedStorageFile sf = new IsolatedStorageFile();
  185.             sf.InitStore(scope, applicationEvidenceType);
  186.             sf.Init(scope);
  187.             return sf;
  188.         }
  189.        
  190.         [ResourceExposure(ResourceScope.Machine | ResourceScope.Assembly)]
  191.         [ResourceConsumption(ResourceScope.Machine | ResourceScope.Assembly)]
  192.         public static IsolatedStorageFile GetStore(IsolatedStorageScope scope, object applicationIdentity)
  193.         {
  194.             if (applicationIdentity == null)
  195.                 throw new ArgumentNullException("applicationIdentity");
  196.            
  197.             DemandAdminPermission();
  198.            
  199.             IsolatedStorageFile sf = new IsolatedStorageFile();
  200.             sf.InitStore(scope, null, null, applicationIdentity);
  201.             sf.Init(scope);
  202.            
  203.             return sf;
  204.         }
  205.        
  206.         [CLSCompliant(false)]
  207.         public override ulong CurrentSize {
  208.             get {
  209.                 if (IsRoaming())
  210.                     throw new InvalidOperationException(Environment.GetResourceString("IsolatedStorage_CurrentSizeUndefined"));
  211.                
  212.                 lock (this) {
  213.                     if (m_bDisposed)
  214.                         throw new ObjectDisposedException(null, Environment.GetResourceString("IsolatedStorage_StoreNotOpen"));
  215.                    
  216.                     if (m_closed)
  217.                         throw new InvalidOperationException(Environment.GetResourceString("IsolatedStorage_StoreNotOpen"));
  218.                    
  219.                     if (m_handle == Win32Native.NULL)
  220.                         m_handle = nOpen(m_InfoFile, GetSyncObjectName());
  221.                    
  222.                     return nGetUsage(m_handle);
  223.                 }
  224.             }
  225.         }
  226.        
  227.         [CLSCompliant(false)]
  228.         public override ulong MaximumSize {
  229.             get {
  230.                 if (IsRoaming())
  231.                     return Int64.MaxValue;
  232.                
  233.                 return base.MaximumSize;
  234.             }
  235.         }
  236.        
  237.         unsafe internal void Reserve(ulong lReserve)
  238.         {
  239.             if (IsRoaming())
  240.                 // No Quota enforcement for roaming
  241.                 return;
  242.            
  243.             ulong quota = this.MaximumSize;
  244.             ulong reserve = lReserve;
  245.            
  246.             lock (this) {
  247.                 if (m_bDisposed)
  248.                     throw new ObjectDisposedException(null, Environment.GetResourceString("IsolatedStorage_StoreNotOpen"));
  249.                
  250.                 if (m_closed)
  251.                     throw new InvalidOperationException(Environment.GetResourceString("IsolatedStorage_StoreNotOpen"));
  252.                
  253.                 if (m_handle == Win32Native.NULL)
  254.                     m_handle = nOpen(m_InfoFile, GetSyncObjectName());
  255.                
  256.                 nReserve(m_handle, &quota, &reserve, false);
  257.             }
  258.         }
  259.        
  260.         unsafe internal void Unreserve(ulong lFree)
  261.         {
  262.             if (IsRoaming())
  263.                 // No Quota enforcement for roaming
  264.                 return;
  265.            
  266.             ulong quota = this.MaximumSize;
  267.             ulong free = lFree;
  268.            
  269.             lock (this) {
  270.                 if (m_bDisposed)
  271.                     throw new ObjectDisposedException(null, Environment.GetResourceString("IsolatedStorage_StoreNotOpen"));
  272.                
  273.                 if (m_closed)
  274.                     throw new InvalidOperationException(Environment.GetResourceString("IsolatedStorage_StoreNotOpen"));
  275.                
  276.                 if (m_handle == Win32Native.NULL)
  277.                     m_handle = nOpen(m_InfoFile, GetSyncObjectName());
  278.                
  279.                 nReserve(m_handle, &quota, &free, true);
  280.             }
  281.         }
  282.        
  283.         [ResourceExposure(ResourceScope.Machine | ResourceScope.Assembly)]
  284.         [ResourceConsumption(ResourceScope.Machine, ResourceScope.Machine)]
  285.         public void DeleteFile(string file)
  286.         {
  287.             if (file == null)
  288.                 throw new ArgumentNullException("file");
  289.            
  290.             m_fiop.Assert();
  291.             m_fiop.PermitOnly();
  292.            
  293.             FileInfo f = new FileInfo(GetFullPath(file));
  294.             long oldLen = 0;
  295.            
  296.             Lock();
  297.             // protect oldLen
  298.             try {
  299.                 try {
  300.                     oldLen = f.Length;
  301.                     f.Delete();
  302.                 }
  303.                 catch {
  304.                     throw new IsolatedStorageException(Environment.GetResourceString("IsolatedStorage_DeleteFile"));
  305.                 }
  306.                 Unreserve(RoundToBlockSize((ulong)oldLen));
  307.             }
  308.             finally {
  309.                 Unlock();
  310.             }
  311.             CodeAccessPermission.RevertAll();
  312.            
  313.         }
  314.        
  315.         [ResourceExposure(ResourceScope.None)]
  316.         // Scoping should be done when opening isolated storage
  317.         [ResourceConsumption(ResourceScope.Machine, ResourceScope.Machine)]
  318.         public void CreateDirectory(string dir)
  319.         {
  320.             if (dir == null)
  321.                 throw new ArgumentNullException("dir");
  322.            
  323.             string isPath = GetFullPath(dir);
  324.             // Prepend IS root
  325.             string fullPath = Path.GetFullPathInternal(isPath);
  326.            
  327.             string[] dirList = DirectoriesToCreate(fullPath);
  328.            
  329.             if (dirList == null || dirList.Length == 0) {
  330.                 if (Directory.Exists(isPath))
  331.                     return;
  332.                 else
  333.                     throw new IsolatedStorageException(Environment.GetResourceString("IsolatedStorage_CreateDirectory"));
  334.             }
  335.             Reserve(s_DirSize * ((ulong)dirList.Length));
  336.             m_fiop.Assert();
  337.             m_fiop.PermitOnly();
  338.             try {
  339.                 Directory.CreateDirectory(dirList[dirList.Length - 1]);
  340.             }
  341.             catch {
  342.                 Unreserve(s_DirSize * ((ulong)dirList.Length));
  343.                 // force delete any new directories we created
  344.                 Directory.Delete(dirList[0], true);
  345.                 throw new IsolatedStorageException(Environment.GetResourceString("IsolatedStorage_CreateDirectory"));
  346.             }
  347.             CodeAccessPermission.RevertAll();
  348.            
  349.         }
  350.        
  351.         // Given a path to a dir to create, will return the list of directories to create and the last one in the array is the actual dir to create.
  352.         // for example if dir is a\\b\\c and none of them exist, the list returned will be a, a\\b, a\\b\\c.
  353.         private string[] DirectoriesToCreate(string fullPath)
  354.         {
  355.            
  356.             ArrayList list = new ArrayList();
  357.             int length = fullPath.Length;
  358.            
  359.             // We need to trim the trailing slash or the code will try to create 2 directories of the same name.
  360.             if (length >= 2 && fullPath[length - 1] == SeparatorExternal)
  361.                 length--;
  362.             int i = Path.GetRootLength(fullPath);
  363.            
  364.             // Attempt to figure out which directories don't exist
  365.             while (i < length) {
  366.                 i++;
  367.                 while (i < length && fullPath[i] != SeparatorExternal)
  368.                     i++;
  369.                 string currDir = fullPath.Substring(0, i);
  370.                
  371.                 if (!Directory.InternalExists(currDir)) {
  372.                     // Create only the ones missing
  373.                     list.Add(currDir);
  374.                 }
  375.             }
  376.            
  377.             if (list.Count != 0) {
  378.                 return (string[])list.ToArray(typeof(string));
  379.             }
  380.             return null;
  381.         }
  382.        
  383.         public void DeleteDirectory(string dir)
  384.         {
  385.             if (dir == null)
  386.                 throw new ArgumentNullException("dir");
  387.            
  388.             m_fiop.Assert();
  389.             m_fiop.PermitOnly();
  390.            
  391.             Lock();
  392.             // Delete *.*, will beat quota enforcement without this lock
  393.             try {
  394.                 try {
  395.                     new DirectoryInfo(GetFullPath(dir)).Delete(false);
  396.                 }
  397.                 catch {
  398.                     throw new IsolatedStorageException(Environment.GetResourceString("IsolatedStorage_DeleteDirectory"));
  399.                 }
  400.                 Unreserve(s_DirSize);
  401.             }
  402.             finally {
  403.                 Unlock();
  404.             }
  405.             CodeAccessPermission.RevertAll();
  406.         }
  407.        
  408. /*
  409.         * foo\abc*.txt will give all abc*.txt files in foo directory
  410.         */       
  411.         public string[] GetFileNames(string searchPattern)
  412.         {
  413.             if (searchPattern == null)
  414.                 throw new ArgumentNullException("searchPattern");
  415.            
  416.             m_fiop.Assert();
  417.             m_fiop.PermitOnly();
  418.             string[] retVal = GetFileDirectoryNames(GetFullPath(searchPattern), searchPattern, true);
  419.             CodeAccessPermission.RevertAll();
  420.             return retVal;
  421.            
  422.         }
  423.        
  424. /*
  425.         * foo\data* will give all directory names in foo directory that
  426.         * starts with data
  427.         */       
  428.         [ResourceExposure(ResourceScope.None)]
  429.         // Scoping should be done when opening isolated storage.
  430.         [ResourceConsumption(ResourceScope.Machine, ResourceScope.Machine)]
  431.         public string[] GetDirectoryNames(string searchPattern)
  432.         {
  433.             if (searchPattern == null)
  434.                 throw new ArgumentNullException("searchPattern");
  435.            
  436.             m_fiop.Assert();
  437.             m_fiop.PermitOnly();
  438.             string[] retVal = GetFileDirectoryNames(GetFullPath(searchPattern), searchPattern, false);
  439.             CodeAccessPermission.RevertAll();
  440.             return retVal;
  441.         }
  442.        
  443.         // Remove this individual store
  444.         [ResourceExposure(ResourceScope.None)]
  445.         // Scoping should be done when opening isolated storage.
  446.         [ResourceConsumption(ResourceScope.Machine, ResourceScope.Machine)]
  447.         public override void Remove()
  448.         {
  449.             // No security check required here since we have already done
  450.             // that during creation
  451.            
  452.             string rootDir;
  453.             string domainRoot = null;
  454.            
  455.             // First remove the logical root directory of this store, this
  456.             // will not delete the quota file. Removes all the files and dirs
  457.             // that applications see.
  458.            
  459.             RemoveLogicalDir();
  460.            
  461.             Close();
  462.            
  463.             // Now try to remove other files folders that become unnecessary
  464.             // if the application directory is deleted.
  465.            
  466.             StringBuilder sb = new StringBuilder();
  467.            
  468.             sb.Append(GetRootDir(this.Scope));
  469.            
  470.             if (IsApp()) {
  471.                 sb.Append(this.AppName);
  472.                 sb.Append(this.SeparatorExternal);
  473.             }
  474.             else {
  475.                 if (IsDomain()) {
  476.                     sb.Append(this.DomainName);
  477.                     sb.Append(this.SeparatorExternal);
  478.                     domainRoot = sb.ToString();
  479.                 }
  480.                
  481.                 sb.Append(this.AssemName);
  482.                 sb.Append(this.SeparatorExternal);
  483.             }
  484.             rootDir = sb.ToString();
  485.            
  486.             new FileIOPermission(FileIOPermissionAccess.AllAccess, rootDir).Assert();
  487.            
  488.             if (ContainsUnknownFiles(rootDir))
  489.                 return;
  490.            
  491.             try {
  492.                
  493.                 Directory.Delete(rootDir, true);
  494.                 #if _DEBUG
  495.             }
  496.             catch (Exception e) {
  497.                
  498.                 if (s_fDebug) {
  499.                     Console.WriteLine(e);
  500.                     Console.WriteLine("Delete failed on rootdir");
  501.                 }
  502.                 #else
  503.             }
  504.             catch {
  505.                 #endif
  506.                 return;
  507.                 // OK to ignore this exception.
  508.             }
  509.            
  510.             // If this was a domain store, and if this happens to be
  511.             // the only store around, then delete the root store for this
  512.             // domain
  513.            
  514.             if (IsDomain()) {
  515.                 CodeAccessPermission.RevertAssert();
  516.                
  517.                 new FileIOPermission(FileIOPermissionAccess.AllAccess, domainRoot).Assert();
  518.                
  519.                 if (!ContainsUnknownFiles(domainRoot)) {
  520.                    
  521.                     try {
  522.                        
  523.                         Directory.Delete(domainRoot, true);
  524.                         #if _DEBUG
  525.                     }
  526.                     catch (Exception e) {
  527.                        
  528.                         if (s_fDebug) {
  529.                             Console.WriteLine(e);
  530.                             Console.WriteLine("Delete failed on basedir");
  531.                         }
  532.                         #else
  533.                     }
  534.                     catch {
  535.                         #endif
  536.                         return;
  537.                         // OK to ignore this exception.
  538.                     }
  539.                 }
  540.             }
  541.         }
  542.        
  543.         [ResourceExposure(ResourceScope.None)]
  544.         // Scoping should be done when opening isolated storage.
  545.         [ResourceConsumption(ResourceScope.Machine, ResourceScope.Machine)]
  546.         private void RemoveLogicalDir()
  547.         {
  548.             m_fiop.Assert();
  549.            
  550.             ulong oldLen;
  551.            
  552.             Lock();
  553.             // A race here with delete dir/delete file can get around
  554.             // quota enforcement.
  555.             try {
  556.                 oldLen = IsRoaming() ? 0 : CurrentSize;
  557.                
  558.                 try {
  559.                    
  560.                     Directory.Delete(RootDirectory, true);
  561.                     #if _DEBUG
  562.                 }
  563.                 catch (Exception e) {
  564.                    
  565.                     if (s_fDebug) {
  566.                         Console.WriteLine(e);
  567.                         Console.WriteLine("Delete failed on LogicalRooDir");
  568.                     }
  569.                     #else
  570.                 }
  571.                 catch {
  572.                     #endif
  573.                     throw new IsolatedStorageException(Environment.GetResourceString("IsolatedStorage_DeleteDirectories"));
  574.                 }
  575.                
  576.                 Unreserve(oldLen);
  577.             }
  578.             finally {
  579.                 Unlock();
  580.             }
  581.         }
  582.        
  583.         private bool ContainsUnknownFiles(string rootDir)
  584.         {
  585.             string[] dirs;
  586.             string[] files;
  587.            
  588.             // Delete everything in the root directory of this store
  589.             // if there are no Domain Stores / other files
  590.             // Make sure that there are no other subdirs present here other
  591.             // than the ones used by IsolatedStorageFile (Cookies in future
  592.             // releases ?)
  593.            
  594.             try {
  595.                 files = GetFileDirectoryNames(rootDir + "*", "*", true);
  596.                 dirs = GetFileDirectoryNames(rootDir + "*", "*", false);
  597.             }
  598.             catch {
  599.                 throw new IsolatedStorageException(Environment.GetResourceString("IsolatedStorage_DeleteDirectories"));
  600.             }
  601.            
  602.             // First see if there are any unkonwn Folders
  603.             if ((dirs != null) && (dirs.Length > 0)) {
  604.                 if (dirs.Length > 1) {
  605.                     // More than one directory present
  606.                     return true;
  607.                 }
  608.                
  609.                 if (IsApp()) {
  610.                     if (NotAppFilesDir(dirs[0]))
  611.                         return true;
  612.                 }
  613.                 else if (IsDomain()) {
  614.                     if (NotFilesDir(dirs[0]))
  615.                         return true;
  616.                 }
  617.                 else {
  618.                     if (NotAssemFilesDir(dirs[0]))
  619.                         return true;
  620.                 }
  621.             }
  622.            
  623.             // Now look at the files
  624.            
  625.             if ((files == null) || (files.Length == 0))
  626.                 return false;
  627.            
  628.             if (IsRoaming()) {
  629.                 if ((files.Length > 1) || NotIDFile(files[0])) {
  630.                     // There is one or more files unknown to this version
  631.                     // of IsoStoreFile
  632.                    
  633.                     return true;
  634.                 }
  635.                
  636.                 return false;
  637.             }
  638.            
  639.             if ((files.Length > 2) || (NotIDFile(files[0]) && NotInfoFile(files[0])) || ((files.Length == 2) && NotIDFile(files[1]) && NotInfoFile(files[1]))) {
  640.                 // There is one or more files unknown to this version
  641.                 // of IsoStoreFile
  642.                
  643.                 return true;
  644.             }
  645.            
  646.             return false;
  647.         }
  648.        
  649.         public void Close()
  650.         {
  651.             if (IsRoaming())
  652.                 return;
  653.            
  654.             lock (this) {
  655.                
  656.                 if (!m_closed) {
  657.                     m_closed = true;
  658.                    
  659.                     IntPtr handle = m_handle;
  660.                    
  661.                     m_handle = Win32Native.NULL;
  662.                     nClose(handle);
  663.                    
  664.                     GC.nativeSuppressFinalize(this);
  665.                 }
  666.                
  667.             }
  668.         }
  669.        
  670.         public void Dispose()
  671.         {
  672.             Close();
  673.             m_bDisposed = true;
  674.         }
  675.        
  676.         ~IsolatedStorageFile()
  677.         {
  678.             Dispose();
  679.         }
  680.        
  681.         // Macros, expect JIT to expand this
  682.         private static bool NotIDFile(string file)
  683.         {
  684.             return (String.Compare(file, IsolatedStorageFile.s_IDFile, StringComparison.Ordinal) != 0);
  685.         }
  686.        
  687.         private static bool NotInfoFile(string file)
  688.         {
  689.             return (String.Compare(file, IsolatedStorageFile.s_InfoFile, StringComparison.Ordinal) != 0 && String.Compare(file, IsolatedStorageFile.s_AppInfoFile, StringComparison.Ordinal) != 0);
  690.         }
  691.        
  692.         private static bool NotFilesDir(string dir)
  693.         {
  694.             return (String.Compare(dir, IsolatedStorageFile.s_Files, StringComparison.Ordinal) != 0);
  695.         }
  696.        
  697.         static internal bool NotAssemFilesDir(string dir)
  698.         {
  699.             return (String.Compare(dir, IsolatedStorageFile.s_AssemFiles, StringComparison.Ordinal) != 0);
  700.         }
  701.        
  702.         static internal bool NotAppFilesDir(string dir)
  703.         {
  704.             return (String.Compare(dir, IsolatedStorageFile.s_AppFiles, StringComparison.Ordinal) != 0);
  705.         }
  706.        
  707.         // Remove store for all identities
  708.         [ResourceExposure(ResourceScope.None)]
  709.         // Scoping should be done when opening isolated storage.
  710.         [ResourceConsumption(ResourceScope.Machine, ResourceScope.Machine)]
  711.         public static void Remove(IsolatedStorageScope scope)
  712.         {
  713.             VerifyGlobalScope(scope);
  714.             DemandAdminPermission();
  715.            
  716.             string rootDir = GetRootDir(scope);
  717.            
  718.             new FileIOPermission(FileIOPermissionAccess.Write, rootDir).Assert();
  719.            
  720.             try {
  721.                 Directory.Delete(rootDir, true);
  722.                 // Remove all sub dirs and files
  723.                 Directory.CreateDirectory(rootDir);
  724.                 // Recreate the root dir
  725.             }
  726.             catch {
  727.                 throw new IsolatedStorageException(Environment.GetResourceString("IsolatedStorage_DeleteDirectories"));
  728.             }
  729.         }
  730.        
  731.         public static IEnumerator GetEnumerator(IsolatedStorageScope scope)
  732.         {
  733.             VerifyGlobalScope(scope);
  734.             DemandAdminPermission();
  735.            
  736.             return new IsolatedStorageFileEnumerator(scope);
  737.         }
  738.        
  739.         // Internal & private methods
  740.        
  741.         internal string RootDirectory {
  742.             get { return m_RootDir; }
  743.         }
  744.        
  745.         // RootDirectory has been scoped already.
  746.         internal string GetFullPath(string path)
  747.         {
  748.             StringBuilder sb = new StringBuilder();
  749.            
  750.             sb.Append(this.RootDirectory);
  751.            
  752.             if (path[0] == SeparatorExternal)
  753.                 sb.Append(path.Substring(1));
  754.             else
  755.                 sb.Append(path);
  756.            
  757.             return sb.ToString();
  758.         }
  759.        
  760.        
  761.         [ResourceExposure(ResourceScope.Machine | ResourceScope.Assembly)]
  762.         [ResourceConsumption(ResourceScope.Machine, ResourceScope.Machine | ResourceScope.Assembly)]
  763.         internal void Init(IsolatedStorageScope scope)
  764.         {
  765.             GetGlobalFileIOPerm(scope).Assert();
  766.            
  767.             StringBuilder sb = new StringBuilder();
  768.            
  769.             // Create the root directory if it is not already there
  770.            
  771.            
  772.             if (IsApp(scope)) {
  773.                 throw new IsolatedStorageException(Environment.GetResourceString("IsolatedStorage_ApplicationMissingIdentity"));
  774.                
  775.                 sb.Append(GetRootDir(scope));
  776.                 if (s_appDataDir == null) {
  777.                     // We're not using the App Data directory...so we need to append AppName
  778.                     sb.Append(this.AppName);
  779.                     sb.Append(this.SeparatorExternal);
  780.                 }
  781.                
  782.                 try {
  783.                    
  784.                     Directory.CreateDirectory(sb.ToString());
  785.                    
  786.                     // No exception implies this directory was created now
  787.                    
  788.                    
  789.                 }
  790.                 catch {
  791.                     // Ok to ignore IO exception
  792.                    
  793.                 }
  794.                 // Create the Identity blob file in the root
  795.                 // directory. OK if there are more than one created
  796.                 // last one wins
  797.                
  798.                 CreateIDFile(sb.ToString(), scope);
  799.                
  800.                 // For App Stores, accounting is done in the app root
  801.                 this.m_InfoFile = sb.ToString() + s_AppInfoFile;
  802.                
  803.                 sb.Append(s_AppFiles);
  804.                
  805.             }
  806.             else {
  807.                 sb.Append(GetRootDir(scope));
  808.                 if (IsDomain(scope)) {
  809.                     sb.Append(this.DomainName);
  810.                     sb.Append(this.SeparatorExternal);
  811.                    
  812.                     try {
  813.                        
  814.                         Directory.CreateDirectory(sb.ToString());
  815.                        
  816.                         // No exception implies this directory was created now
  817.                        
  818.                         // Create the Identity blob file in the root
  819.                         // directory. OK if there are more than one created
  820.                         // last one wins
  821.                        
  822.                         CreateIDFile(sb.ToString(), scope);
  823.                        
  824.                     }
  825.                     catch {
  826.                        
  827.                         // Ok to ignore IO exception
  828.                        
  829.                     }
  830.                    
  831.                     // For Domain Stores, accounting is done in the domain root
  832.                     this.m_InfoFile = sb.ToString() + s_InfoFile;
  833.                 }
  834.                
  835.                 sb.Append(this.AssemName);
  836.                 sb.Append(this.SeparatorExternal);
  837.                
  838.                 try {
  839.                    
  840.                     Directory.CreateDirectory(sb.ToString());
  841.                    
  842.                     // No exception implies this directory was created now
  843.                    
  844.                     // Create the Identity blob file in the root
  845.                     // directory. OK if there are more than one created
  846.                     // last one wins
  847.                    
  848.                     CreateIDFile(sb.ToString(), scope);
  849.                    
  850.                 }
  851.                 catch {
  852.                     // Ok to ignore IO exception
  853.                    
  854.                 }
  855.                
  856.                 if (IsDomain(scope)) {
  857.                     sb.Append(s_Files);
  858.                 }
  859.                 else {
  860.                     // For Assem Stores, accounting is done in the assem root
  861.                     this.m_InfoFile = sb.ToString() + s_InfoFile;
  862.                    
  863.                     sb.Append(s_AssemFiles);
  864.                 }
  865.             }
  866.             sb.Append(this.SeparatorExternal);
  867.            
  868.             string rootDir = sb.ToString();
  869.            
  870.             try {
  871.                 Directory.CreateDirectory(rootDir);
  872.             }
  873.             catch {
  874.                 // Ok to ignore IO exception
  875.             }
  876.            
  877.             this.m_RootDir = rootDir;
  878.            
  879.             // Use the "new" RootDirectory to create the permission.
  880.             // This instance of permission is not the same as the
  881.             // one we just asserted. It uses this.base.RootDirectory.
  882.            
  883.             m_fiop = new FileIOPermission(FileIOPermissionAccess.AllAccess, rootDir);
  884.         }
  885.        
  886.         [ResourceExposure(ResourceScope.Machine | ResourceScope.Assembly)]
  887.         [ResourceConsumption(ResourceScope.Machine | ResourceScope.Assembly)]
  888.         internal bool InitExistingStore(IsolatedStorageScope scope)
  889.         {
  890.             FileIOPermission fp;
  891.             StringBuilder sb = new StringBuilder();
  892.            
  893.             sb.Append(GetRootDir(scope));
  894.            
  895.             if (IsApp(scope)) {
  896.                 sb.Append(this.AppName);
  897.                 sb.Append(this.SeparatorExternal);
  898.                 // For App Stores, accounting is done in the app root
  899.                 this.m_InfoFile = sb.ToString() + s_AppInfoFile;
  900.                
  901.                 sb.Append(s_AppFiles);
  902.             }
  903.             else {
  904.                 if (IsDomain(scope)) {
  905.                     sb.Append(this.DomainName);
  906.                     sb.Append(this.SeparatorExternal);
  907.                    
  908.                     // For Domain Stores, accounting is done in the domain root
  909.                     this.m_InfoFile = sb.ToString() + s_InfoFile;
  910.                 }
  911.                
  912.                 sb.Append(this.AssemName);
  913.                 sb.Append(this.SeparatorExternal);
  914.                
  915.                 if (IsDomain(scope)) {
  916.                     sb.Append(s_Files);
  917.                 }
  918.                 else {
  919.                     // For Assem Stores, accounting is done in the assem root
  920.                     this.m_InfoFile = sb.ToString() + s_InfoFile;
  921.                    
  922.                     sb.Append(s_AssemFiles);
  923.                 }
  924.             }
  925.             sb.Append(this.SeparatorExternal);
  926.            
  927.             fp = new FileIOPermission(FileIOPermissionAccess.AllAccess, sb.ToString());
  928.            
  929.             fp.Assert();
  930.            
  931.             if (!Directory.Exists(sb.ToString()))
  932.                 return false;
  933.            
  934.             this.m_RootDir = sb.ToString();
  935.             this.m_fiop = fp;
  936.            
  937.             return true;
  938.         }
  939.        
  940.         protected override IsolatedStoragePermission GetPermission(PermissionSet ps)
  941.         {
  942.             if (ps == null)
  943.                 return null;
  944.             else if (ps.IsUnrestricted())
  945.                 return new IsolatedStorageFilePermission(PermissionState.Unrestricted);
  946.            
  947.             return (IsolatedStoragePermission)ps.GetPermission(typeof(IsolatedStorageFilePermission));
  948.         }
  949.        
  950.         internal void UndoReserveOperation(ulong oldLen, ulong newLen)
  951.         {
  952.             oldLen = RoundToBlockSize(oldLen);
  953.             if (newLen > oldLen)
  954.                 Unreserve(RoundToBlockSize(newLen - oldLen));
  955.         }
  956.        
  957.         internal void Reserve(ulong oldLen, ulong newLen)
  958.         {
  959.             oldLen = RoundToBlockSize(oldLen);
  960.             if (newLen > oldLen)
  961.                 Reserve(RoundToBlockSize(newLen - oldLen));
  962.         }
  963.        
  964.         internal void ReserveOneBlock()
  965.         {
  966.             Reserve(s_BlockSize);
  967.         }
  968.        
  969.         internal void UnreserveOneBlock()
  970.         {
  971.             Unreserve(s_BlockSize);
  972.         }
  973.        
  974.         static internal ulong RoundToBlockSize(ulong num)
  975.         {
  976.             if (num < s_BlockSize)
  977.                 return s_BlockSize;
  978.            
  979.             ulong rem = (num % s_BlockSize);
  980.            
  981.             if (rem != 0)
  982.                 num += (s_BlockSize - rem);
  983.            
  984.             return num;
  985.         }
  986.        
  987.         // Helper static methods
  988.         static internal string GetRootDir(IsolatedStorageScope scope)
  989.         {
  990.             if (IsRoaming(scope)) {
  991.                 if (s_RootDirRoaming == null)
  992.                     s_RootDirRoaming = nGetRootDir(scope);
  993.                
  994.                 return s_RootDirRoaming;
  995.             }
  996.            
  997.             if (IsMachine(scope)) {
  998.                 if (s_RootDirMachine == null)
  999.                     InitGlobalsMachine(scope);
  1000.                
  1001.                 return s_RootDirMachine;
  1002.             }
  1003.            
  1004.             // This is then the non-roaming user store.
  1005.             if (s_RootDirUser == null)
  1006.                 InitGlobalsNonRoamingUser(scope);
  1007.            
  1008.             return s_RootDirUser;
  1009.         }
  1010.        
  1011.         private static void InitGlobalsMachine(IsolatedStorageScope scope)
  1012.         {
  1013.             string rootDir = nGetRootDir(scope);
  1014.             new FileIOPermission(FileIOPermissionAccess.AllAccess, rootDir).Assert();
  1015.             string rndName = GetMachineRandomDirectory(rootDir);
  1016.             if (rndName == null) {
  1017.                 // Create a random directory
  1018.                 Mutex m = CreateMutexNotOwned(rootDir);
  1019.                 if (!m.WaitOne())
  1020.                     throw new IsolatedStorageException(Environment.GetResourceString("IsolatedStorage_Init"));
  1021.                 try {
  1022.                     // finally...
  1023.                     rndName = GetMachineRandomDirectory(rootDir);
  1024.                     // try again with lock
  1025.                     if (rndName == null) {
  1026.                         string relRandomDirectory1 = Path.GetRandomFileName();
  1027.                         string relRandomDirectory2 = Path.GetRandomFileName();
  1028.                         try {
  1029.                             nCreateDirectoryWithDacl(rootDir + relRandomDirectory1);
  1030.                             // Now create the root directory with the correct DACL
  1031.                             nCreateDirectoryWithDacl(rootDir + relRandomDirectory1 + "\\" + relRandomDirectory2);
  1032.                         }
  1033.                         catch {
  1034.                             // We don't want to leak any information here
  1035.                             // Throw a store initialization exception instead
  1036.                             throw new IsolatedStorageException(Environment.GetResourceString("IsolatedStorage_Init"));
  1037.                         }
  1038.                         rndName = relRandomDirectory1 + "\\" + relRandomDirectory2;
  1039.                     }
  1040.                 }
  1041.                 finally {
  1042.                     m.ReleaseMutex();
  1043.                 }
  1044.             }
  1045.             s_RootDirMachine = rootDir + rndName + "\\";
  1046.         }
  1047.        
  1048.         private static void InitGlobalsNonRoamingUser(IsolatedStorageScope scope)
  1049.         {
  1050.             string rootDir = null;
  1051.             // Non App Data directory case or non-App case:
  1052.             rootDir = nGetRootDir(scope);
  1053.             new FileIOPermission(FileIOPermissionAccess.AllAccess, rootDir).Assert();
  1054.             bool bMigrateNeeded = false;
  1055.             string sOldStoreLocation = null;
  1056.             string rndName = GetRandomDirectory(rootDir, out bMigrateNeeded, out sOldStoreLocation);
  1057.             if (rndName == null) {
  1058.                 // Create a random directory
  1059.                 Mutex m = CreateMutexNotOwned(rootDir);
  1060.                 if (!m.WaitOne())
  1061.                     throw new IsolatedStorageException(Environment.GetResourceString("IsolatedStorage_Init"));
  1062.                 try {
  1063.                     // finally...
  1064.                     rndName = GetRandomDirectory(rootDir, out bMigrateNeeded, out sOldStoreLocation);
  1065.                     // try again with lock
  1066.                     if (rndName == null) {
  1067.                         if (bMigrateNeeded) {
  1068.                             // We have a store directory in the old format; we need to migrate it
  1069.                             rndName = MigrateOldIsoStoreDirectory(rootDir, sOldStoreLocation);
  1070.                         }
  1071.                         else {
  1072.                             rndName = CreateRandomDirectory(rootDir);
  1073.                         }
  1074.                     }
  1075.                 }
  1076.                 finally {
  1077.                     m.ReleaseMutex();
  1078.                 }
  1079.             }
  1080.             s_RootDirUser = rootDir + rndName + "\\";
  1081.         }
  1082.        
  1083.         // Migrates the old store location to a new one and returns the new location without the path separator
  1084.         [ResourceExposure(ResourceScope.Machine | ResourceScope.Assembly)]
  1085.         [ResourceConsumption(ResourceScope.Machine, ResourceScope.Machine | ResourceScope.Assembly)]
  1086.         static internal string MigrateOldIsoStoreDirectory(string rootDir, string oldRandomDirectory)
  1087.         {
  1088.             // First create the new random directory
  1089.             string relRandomDirectory1 = Path.GetRandomFileName();
  1090.             string relRandomDirectory2 = Path.GetRandomFileName();
  1091.             string firstRandomDirectory = rootDir + relRandomDirectory1;
  1092.             string newRandomDirectory = firstRandomDirectory + "\\" + relRandomDirectory2;
  1093.             // Move the old directory to the new location, throw an exception and revert
  1094.             // the transaction if the operation is not successful
  1095.             try {
  1096.                 // Create the first level of the new random directory
  1097.                 Directory.CreateDirectory(firstRandomDirectory);
  1098.                 // Move the old directory under the newly created random directory
  1099.                 Directory.Move(rootDir + oldRandomDirectory, newRandomDirectory);
  1100.             }
  1101.             catch {
  1102.                 // We don't want to leak any information here.
  1103.                 // Throw a store initialization exception instead
  1104.                 throw new IsolatedStorageException(Environment.GetResourceString("IsolatedStorage_Init"));
  1105.             }
  1106.             return (relRandomDirectory1 + "\\" + relRandomDirectory2);
  1107.         }
  1108.        
  1109.         // creates and returns the relative path to the random directory string without the path separator
  1110.         [ResourceExposure(ResourceScope.Assembly | ResourceScope.Machine)]
  1111.         [ResourceConsumption(ResourceScope.Machine, ResourceScope.Assembly | ResourceScope.Machine)]
  1112.         static internal string CreateRandomDirectory(string rootDir)
  1113.         {
  1114.             string rndName = Path.GetRandomFileName() + "\\" + Path.GetRandomFileName();
  1115.             try {
  1116.                 Directory.CreateDirectory(rootDir + rndName);
  1117.             }
  1118.             catch {
  1119.                 // We don't want to leak any information here
  1120.                 // Throw a store initialization exception instead
  1121.                 throw new IsolatedStorageException(Environment.GetResourceString("IsolatedStorage_Init"));
  1122.             }
  1123.             return rndName;
  1124.         }
  1125.        
  1126.         // returns the relative path to the current random directory string if one is there without the path separator
  1127.         [ResourceExposure(ResourceScope.Machine)]
  1128.         [ResourceConsumption(ResourceScope.Machine)]
  1129.         static internal string GetRandomDirectory(string rootDir, out bool bMigrateNeeded, out string sOldStoreLocation)
  1130.         {
  1131.             // Initialize Out Parameters
  1132.             bMigrateNeeded = false;
  1133.             sOldStoreLocation = null;
  1134.             string[] nodes1 = GetFileDirectoryNames(rootDir + "*", "*", false);
  1135.             // First see if there is a new store
  1136.             for (int i = 0; i < nodes1.Length; ++i) {
  1137.                 if (nodes1[i].Length == 12) {
  1138.                     string[] nodes2 = GetFileDirectoryNames(rootDir + nodes1[i] + "\\" + "*", "*", false);
  1139.                     for (int j = 0; j < nodes2.Length; ++j) {
  1140.                         if (nodes2[j].Length == 12) {
  1141.                             return (nodes1[i] + "\\" + nodes2[j]);
  1142.                             // Get the first directory
  1143.                         }
  1144.                     }
  1145.                 }
  1146.             }
  1147.             // We look for directories of length 24: if we find one
  1148.             // it means we are still using the old random directory format.
  1149.             // In that case, migrate to a new store
  1150.             for (int i = 0; i < nodes1.Length; ++i) {
  1151.                 if (nodes1[i].Length == 24) {
  1152.                     bMigrateNeeded = true;
  1153.                     sOldStoreLocation = nodes1[i];
  1154.                     // set the old store location
  1155.                     return null;
  1156.                 }
  1157.             }
  1158.             // Neither old or new store formats have been encountered, return null
  1159.             return null;
  1160.         }
  1161.        
  1162.         // returns the relative path to the current random directory string if one is there without the path separator
  1163.         static internal string GetMachineRandomDirectory(string rootDir)
  1164.         {
  1165.             string[] nodes1 = GetFileDirectoryNames(rootDir + "*", "*", false);
  1166.             // First see if there is a new store
  1167.             for (int i = 0; i < nodes1.Length; ++i) {
  1168.                 if (nodes1[i].Length == 12) {
  1169.                     string[] nodes2 = GetFileDirectoryNames(rootDir + nodes1[i] + "\\" + "*", "*", false);
  1170.                     for (int j = 0; j < nodes2.Length; ++j) {
  1171.                         if (nodes2[j].Length == 12) {
  1172.                             return (nodes1[i] + "\\" + nodes2[j]);
  1173.                             // Get the first directory
  1174.                         }
  1175.                     }
  1176.                 }
  1177.             }
  1178.            
  1179.             // No store has been encountered, return null
  1180.             return null;
  1181.         }
  1182.        
  1183.         static internal Mutex CreateMutexNotOwned(string pathName)
  1184.         {
  1185.             return new Mutex(false, "Global\\" + GetStrongHashSuitableForObjectName(pathName));
  1186.         }
  1187.        
  1188.         static internal string GetStrongHashSuitableForObjectName(string name)
  1189.         {
  1190.             MemoryStream ms = new MemoryStream();
  1191.             new BinaryWriter(ms).Write(name.ToUpper(CultureInfo.InvariantCulture));
  1192.             ms.Position = 0;
  1193.             return GetHash(ms);
  1194.         }
  1195.        
  1196.         private string GetSyncObjectName()
  1197.         {
  1198.             if (m_SyncObjectName == null) {
  1199.                 // Don't take a lock here, ok to create multiple times
  1200.                 m_SyncObjectName = GetStrongHashSuitableForObjectName(m_InfoFile);
  1201.             }
  1202.             return m_SyncObjectName;
  1203.         }
  1204.        
  1205.         internal void Lock()
  1206.         {
  1207.             if (IsRoaming())
  1208.                 // don't lock Roaming stores
  1209.                 return;
  1210.            
  1211.             lock (this) {
  1212.                 if (m_bDisposed)
  1213.                     throw new ObjectDisposedException(null, Environment.GetResourceString("IsolatedStorage_StoreNotOpen"));
  1214.                
  1215.                 if (m_closed)
  1216.                     throw new InvalidOperationException(Environment.GetResourceString("IsolatedStorage_StoreNotOpen"));
  1217.                
  1218.                 if (m_handle == Win32Native.NULL)
  1219.                     m_handle = nOpen(m_InfoFile, GetSyncObjectName());
  1220.                
  1221.                 nLock(m_handle, true);
  1222.             }
  1223.         }
  1224.        
  1225.         internal void Unlock()
  1226.         {
  1227.             if (IsRoaming())
  1228.                 // don't lock Roaming stores
  1229.                 return;
  1230.            
  1231.             lock (this) {
  1232.                 if (m_bDisposed)
  1233.                     throw new ObjectDisposedException(null, Environment.GetResourceString("IsolatedStorage_StoreNotOpen"));
  1234.                
  1235.                 if (m_closed)
  1236.                     throw new InvalidOperationException(Environment.GetResourceString("IsolatedStorage_StoreNotOpen"));
  1237.                
  1238.                 if (m_handle == Win32Native.NULL)
  1239.                     m_handle = nOpen(m_InfoFile, GetSyncObjectName());
  1240.                
  1241.                 nLock(m_handle, false);
  1242.             }
  1243.         }
  1244.        
  1245.         static internal FileIOPermission GetGlobalFileIOPerm(IsolatedStorageScope scope)
  1246.         {
  1247.             if (IsRoaming(scope)) {
  1248.                 // no sync needed, ok to create multiple instances.
  1249.                 if (s_PermRoaming == null) {
  1250.                     s_PermRoaming = new FileIOPermission(FileIOPermissionAccess.AllAccess, GetRootDir(scope));
  1251.                 }
  1252.                
  1253.                 return s_PermRoaming;
  1254.             }
  1255.            
  1256.             if (IsMachine(scope)) {
  1257.                 // no sync needed, ok to create multiple instances.
  1258.                 if (s_PermMachine == null) {
  1259.                     s_PermMachine = new FileIOPermission(FileIOPermissionAccess.AllAccess, GetRootDir(scope));
  1260.                 }
  1261.                
  1262.                 return s_PermMachine;
  1263.             }
  1264.            
  1265.             // no sync needed, ok to create multiple instances.
  1266.             if (s_PermUser == null) {
  1267.                 s_PermUser = new FileIOPermission(FileIOPermissionAccess.AllAccess, GetRootDir(scope));
  1268.             }
  1269.            
  1270.             return s_PermUser;
  1271.         }
  1272.        
  1273.         private static void DemandAdminPermission()
  1274.         {
  1275.             // Ok if more than one instance is created, no need to sync.
  1276.             if (s_PermAdminUser == null) {
  1277.                 s_PermAdminUser = new IsolatedStorageFilePermission(IsolatedStorageContainment.AdministerIsolatedStorageByUser, 0, false);
  1278.             }
  1279.            
  1280.             s_PermAdminUser.Demand();
  1281.         }
  1282.        
  1283.         static internal void VerifyGlobalScope(IsolatedStorageScope scope)
  1284.         {
  1285.             if ((scope != IsolatedStorageScope.User) && (scope != (IsolatedStorageScope.User | IsolatedStorageScope.Roaming)) && (scope != IsolatedStorageScope.Machine)) {
  1286.                 throw new ArgumentException(Environment.GetResourceString("IsolatedStorage_Scope_U_R_M"));
  1287.             }
  1288.         }
  1289.        
  1290.        
  1291.         internal void CreateIDFile(string path, IsolatedStorageScope scope)
  1292.         {
  1293.             try {
  1294.                 // the default DACL is fine here since we've already set it on the root
  1295.                 using (FileStream fs = new FileStream(path + s_IDFile, FileMode.OpenOrCreate)) {
  1296.                     MemoryStream s = GetIdentityStream(scope);
  1297.                     byte[] b = s.GetBuffer();
  1298.                     fs.Write(b, 0, (int)s.Length);
  1299.                     s.Close();
  1300.                 }
  1301.                
  1302.             }
  1303.             catch {
  1304.                 // OK to ignore. It is possible that another thread / process
  1305.                 // is writing to this file with the same data.
  1306.             }
  1307.         }
  1308.        
  1309.         // From IO.Directory class (make that internal if possible)
  1310.         [ResourceExposure(ResourceScope.Machine | ResourceScope.Assembly)]
  1311.         [ResourceConsumption(ResourceScope.Machine | ResourceScope.Assembly)]
  1312.         private static string[] GetFileDirectoryNames(string path, string msg, bool file)
  1313.         {
  1314.             int hr;
  1315.            
  1316.             if (path == null)
  1317.                 throw new ArgumentNullException("path", Environment.GetResourceString("ArgumentNull_Path"));
  1318.            
  1319.             bool fEndsWithDirectory = false;
  1320.             char lastChar = path[path.Length - 1];
  1321.             if (lastChar == Path.DirectorySeparatorChar || lastChar == Path.AltDirectorySeparatorChar || lastChar == '.')
  1322.                 fEndsWithDirectory = true;
  1323.            
  1324.            
  1325.             // Get an absolute path and do a security check
  1326.             string fullPath = Path.GetFullPathInternal(path);
  1327.            
  1328.             // GetFullPath() removes '\', "\." etc from path, we will restore
  1329.             // it here. If path ends in a trailing slash (\), append a *
  1330.             // or we'll get a "Cannot find the file specified" exception
  1331.             if ((fEndsWithDirectory) && (fullPath[fullPath.Length - 1] != lastChar))
  1332.                 fullPath += "\\*";
  1333.            
  1334.             // Check for read permission to the directory, not to the contents.
  1335.             string dir = Path.GetDirectoryName(fullPath);
  1336.            
  1337.             if (dir != null)
  1338.                 dir += "\\";
  1339.            
  1340.             #if _DEBUG
  1341.             if (s_fDebug) {
  1342.                 Console.WriteLine("path = " + path);
  1343.                 Console.WriteLine("fullPath = " + fullPath);
  1344.                 Console.WriteLine("dir = " + dir);
  1345.             }
  1346.             #endif
  1347.            
  1348.             new FileIOPermission(FileIOPermissionAccess.Read, dir == null ? fullPath : dir).Demand();
  1349.            
  1350.            
  1351.             string[] list = new string[10];
  1352.             int listSize = 0;
  1353.             Win32Native.WIN32_FIND_DATA data = new Win32Native.WIN32_FIND_DATA();
  1354.            
  1355.             // Open a Find handle
  1356.             SafeFindHandle hnd = Win32Native.FindFirstFile(fullPath, data);
  1357.             if (hnd.IsInvalid) {
  1358.                 // Calls to GetLastWin32Error overwrites HResult. Store HResult.
  1359.                 hr = Marshal.GetLastWin32Error();
  1360.                 if (hr == Win32Native.ERROR_FILE_NOT_FOUND)
  1361.                     return new string[0];
  1362.                 __Error.WinIOError(hr, msg);
  1363.             }
  1364.            
  1365.             // Keep asking for more matching files, adding file names to list
  1366.             int numEntries = 0;
  1367.             // Number of directory entities we see.
  1368.             do {
  1369.                 bool includeThis;
  1370.                 // Should this file/directory be included in the output?
  1371.                 if (file)
  1372.                     includeThis = (0 == (data.dwFileAttributes & Win32Native.FILE_ATTRIBUTE_DIRECTORY));
  1373.                 else {
  1374.                     includeThis = (0 != (data.dwFileAttributes & Win32Native.FILE_ATTRIBUTE_DIRECTORY));
  1375.                     // Don't add "." nor ".."
  1376.                     if (includeThis && (data.cFileName.Equals(".") || data.cFileName.Equals("..")))
  1377.                         includeThis = false;
  1378.                 }
  1379.                
  1380.                 if (includeThis) {
  1381.                     numEntries++;
  1382.                     if (listSize == list.Length) {
  1383.                         string[] newList = new string[list.Length * 2];
  1384.                         Array.Copy(list, 0, newList, 0, listSize);
  1385.                         list = newList;
  1386.                     }
  1387.                     list[listSize++] = data.cFileName;
  1388.                 }
  1389.                
  1390.             }
  1391.             while (Win32Native.FindNextFile(hnd, data));
  1392.            
  1393.             // Make sure we quit with a sensible error.
  1394.             hr = Marshal.GetLastWin32Error();
  1395.             hnd.Close();
  1396.             // Close Find handle in all cases.
  1397.             if (hr != 0 && hr != Win32Native.ERROR_NO_MORE_FILES)
  1398.                 __Error.WinIOError(hr, msg);
  1399.            
  1400.             // Check for a string such as "C:\tmp", in which case we return
  1401.             // just the directory name. FindNextFile fails first time, and
  1402.             // data still contains a directory.
  1403.             if (!file && numEntries == 1 && (0 != (data.dwFileAttributes & Win32Native.FILE_ATTRIBUTE_DIRECTORY))) {
  1404.                 string[] sa = new string[1];
  1405.                 sa[0] = data.cFileName;
  1406.                 return sa;
  1407.             }
  1408.            
  1409.             // Return list of files/directories as an array of strings
  1410.             if (listSize == list.Length)
  1411.                 return list;
  1412.             string[] items = new string[listSize];
  1413.             Array.Copy(list, 0, items, 0, listSize);
  1414.             return items;
  1415.         }
  1416.        
  1417.         [MethodImplAttribute(MethodImplOptions.InternalCall)]
  1418.         static internal extern ulong nGetUsage(IntPtr handle);
  1419.        
  1420.         [MethodImplAttribute(MethodImplOptions.InternalCall)]
  1421.         static internal extern IntPtr nOpen(string infoFile, string syncName);
  1422.        
  1423.         [MethodImplAttribute(MethodImplOptions.InternalCall)]
  1424.         static internal extern void nClose(IntPtr handle);
  1425.        
  1426.         [MethodImplAttribute(MethodImplOptions.InternalCall)]
  1427.         unsafe static internal extern void nReserve(IntPtr handle, ulong* plQuota, ulong* plReserve, bool fFree);
  1428.        
  1429.         [MethodImplAttribute(MethodImplOptions.InternalCall)]
  1430.         static internal extern string nGetRootDir(IsolatedStorageScope scope);
  1431.        
  1432.         [MethodImplAttribute(MethodImplOptions.InternalCall)]
  1433.         static internal extern void nLock(IntPtr handle, bool fLock);
  1434.        
  1435.         [MethodImplAttribute(MethodImplOptions.InternalCall)]
  1436.         static internal extern void nCreateDirectoryWithDacl(string path);
  1437.        
  1438.     }
  1439.    
  1440.     internal sealed class IsolatedStorageFileEnumerator : IEnumerator
  1441.     {
  1442.         private static readonly char s_SepExternal = System.IO.Path.DirectorySeparatorChar;
  1443.        
  1444.         private IsolatedStorageFile m_Current;
  1445.         private IsolatedStorageScope m_Scope;
  1446.         private FileIOPermission m_fiop;
  1447.         private string m_rootDir;
  1448.        
  1449.         private TwoLevelFileEnumerator m_fileEnum;
  1450.         private bool m_fReset;
  1451.         private bool m_fEnd;
  1452.        
  1453.         #if _DEBUG
  1454.         private static bool s_fDebug;
  1455.         #endif
  1456.        
  1457.         internal IsolatedStorageFileEnumerator(IsolatedStorageScope scope)
  1458.         {
  1459.             m_Scope = scope;
  1460.             m_fiop = IsolatedStorageFile.GetGlobalFileIOPerm(scope);
  1461.             m_rootDir = IsolatedStorageFile.GetRootDir(scope);
  1462.             m_fileEnum = new TwoLevelFileEnumerator(m_rootDir);
  1463.             Reset();
  1464.         }
  1465.        
  1466.         public bool MoveNext()
  1467.         {
  1468.             IsolatedStorageFile isf;
  1469.             IsolatedStorageScope scope;
  1470.             bool fDomain;
  1471.             TwoPaths tp;
  1472.             Stream domain;
  1473.             Stream assem;
  1474.             Stream app;
  1475.             string domainName;
  1476.             string assemName;
  1477.             string appName;
  1478.            
  1479.             m_fiop.Assert();
  1480.            
  1481.             m_fReset = false;
  1482.            
  1483.             do {
  1484.                
  1485.                 if (m_fileEnum.MoveNext() == false) {
  1486.                     m_fEnd = true;
  1487.                     break;
  1488.                 }
  1489.                
  1490.                 // Create the store
  1491.                 isf = new IsolatedStorageFile();
  1492.                
  1493.                 tp = (TwoPaths)m_fileEnum.Current;
  1494.                 fDomain = false;
  1495.                
  1496.                 #if _DEBUG
  1497.                 if (s_fDebug) {
  1498.                     Console.Write(tp.Path1 + " ");
  1499.                     Console.WriteLine(tp.Path2);
  1500.                 }
  1501.                 #endif
  1502.                
  1503.                 if (IsolatedStorageFile.NotAssemFilesDir(tp.Path2) && IsolatedStorageFile.NotAppFilesDir(tp.Path2))
  1504.                     fDomain = true;
  1505.                
  1506.                 // Create Roaming Store
  1507.                 domain = null;
  1508.                 assem = null;
  1509.                 app = null;
  1510.                
  1511.                 if (fDomain) {
  1512.                     if (!GetIDStream(tp.Path1, out domain))
  1513.                         continue;
  1514.                    
  1515.                     if (!GetIDStream(tp.Path1 + s_SepExternal + tp.Path2, out assem))
  1516.                         continue;
  1517.                    
  1518.                     domain.Position = 0;
  1519.                    
  1520.                     if (IsolatedStorage.IsRoaming(m_Scope))
  1521.                         scope = IsolatedStorage.c_DomainRoaming;
  1522.                     else if (IsolatedStorage.IsMachine(m_Scope))
  1523.                         scope = IsolatedStorage.c_MachineDomain;
  1524.                     else
  1525.                         scope = IsolatedStorage.c_Domain;
  1526.                    
  1527.                     domainName = tp.Path1;
  1528.                     assemName = tp.Path2;
  1529.                     appName = null;
  1530.                 }
  1531.                 else {
  1532.                     if (IsolatedStorageFile.NotAppFilesDir(tp.Path2)) {
  1533.                         // Assembly
  1534.                         if (!GetIDStream(tp.Path1, out assem))
  1535.                             continue;
  1536.                        
  1537.                         if (IsolatedStorage.IsRoaming(m_Scope))
  1538.                             scope = IsolatedStorage.c_AssemblyRoaming;
  1539.                         else if (IsolatedStorage.IsMachine(m_Scope))
  1540.                             scope = IsolatedStorage.c_MachineAssembly;
  1541.                         else
  1542.                             scope = IsolatedStorage.c_Assembly;
  1543.                        
  1544.                         domainName = null;
  1545.                         assemName = tp.Path1;
  1546.                         appName = null;
  1547.                         assem.Position = 0;
  1548.                     }
  1549.                     else {
  1550.                         // Application
  1551.                         if (!GetIDStream(tp.Path1, out app))
  1552.                             continue;
  1553.                        
  1554.                         if (IsolatedStorage.IsRoaming(m_Scope))
  1555.                             scope = IsolatedStorage.c_AppUserRoaming;
  1556.                         else if (IsolatedStorage.IsMachine(m_Scope))
  1557.                             scope = IsolatedStorage.c_AppMachine;
  1558.                         else
  1559.                             scope = IsolatedStorage.c_AppUser;
  1560.                        
  1561.                         domainName = null;
  1562.                         assemName = null;
  1563.                         appName = tp.Path1;
  1564.                         app.Position = 0;
  1565.                     }
  1566.                    
  1567.                 }
  1568.                
  1569.                
  1570.                
  1571.                 if (!isf.InitStore(scope, domain, assem, app, domainName, assemName, appName))
  1572.                     continue;
  1573.                
  1574.                 if (!isf.InitExistingStore(scope))
  1575.                     continue;
  1576.                
  1577.                 m_Current = isf;
  1578.                
  1579.                 return true;
  1580.                
  1581.             }
  1582.             while (true);
  1583.             return false;
  1584.         }
  1585.        
  1586.         public object Current {
  1587.             get {
  1588.                
  1589.                 if (m_fReset) {
  1590.                     throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_EnumNotStarted"));
  1591.                 }
  1592.                 else if (m_fEnd) {
  1593.                     throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_EnumEnded"));
  1594.                 }
  1595.                
  1596.                 return (object)m_Current;
  1597.             }
  1598.         }
  1599.        
  1600.         public void Reset()
  1601.         {
  1602.             m_Current = null;
  1603.             m_fReset = true;
  1604.             m_fEnd = false;
  1605.             m_fileEnum.Reset();
  1606.         }
  1607.        
  1608.         private bool GetIDStream(string path, out Stream s)
  1609.         {
  1610.             StringBuilder sb = new StringBuilder();
  1611.             byte[] b;
  1612.            
  1613.             sb.Append(m_rootDir);
  1614.             sb.Append(path);
  1615.             sb.Append(s_SepExternal);
  1616.             sb.Append(IsolatedStorageFile.s_IDFile);
  1617.            
  1618.             s = null;
  1619.            
  1620.             try {
  1621.                 using (FileStream fs = new FileStream(sb.ToString(), FileMode.Open)) {
  1622.                     int length = (int)fs.Length;
  1623.                     b = new byte[length];
  1624.                     int offset = 0;
  1625.                     while (length > 0) {
  1626.                         int n = fs.Read(b, offset, length);
  1627.                         if (n == 0)
  1628.                             __Error.EndOfFile();
  1629.                         offset += n;
  1630.                         length -= n;
  1631.                     }
  1632.                 }
  1633.                 s = new MemoryStream(b);
  1634.             }
  1635.             catch {
  1636.                 return false;
  1637.             }
  1638.            
  1639.             return true;
  1640.         }
  1641.     }
  1642.    
  1643.     internal sealed class TwoPaths
  1644.     {
  1645.         public string Path1;
  1646.         public string Path2;
  1647.        
  1648.     }
  1649.    
  1650.     // Given a directory, enumerates all subdirs of upto depth 2
  1651.     internal sealed class TwoLevelFileEnumerator : IEnumerator
  1652.     {
  1653.         private string m_Root;
  1654.         private TwoPaths m_Current;
  1655.         private bool m_fReset;
  1656.        
  1657.         private string[] m_RootDir;
  1658.         private int m_nRootDir;
  1659.        
  1660.         private string[] m_SubDir;
  1661.         private int m_nSubDir;
  1662.        
  1663.        
  1664.         public TwoLevelFileEnumerator(string root)
  1665.         {
  1666.             m_Root = root;
  1667.             Reset();
  1668.         }
  1669.        
  1670.         public bool MoveNext()
  1671.         {
  1672.             lock (this) {
  1673.                 // Sepecial case the Reset State
  1674.                 if (m_fReset) {
  1675.                     m_fReset = false;
  1676.                     return AdvanceRootDir();
  1677.                 }
  1678.                
  1679.                 // Don't move anything if RootDir is empty
  1680.                 if (m_RootDir.Length == 0)
  1681.                     return false;
  1682.                
  1683.                
  1684.                 // Get Next SubDir
  1685.                
  1686.                 ++m_nSubDir;
  1687.                
  1688.                 if (m_nSubDir >= m_SubDir.Length) {
  1689.                     m_nSubDir = m_SubDir.Length;
  1690.                     // to avoid wrap aournd.
  1691.                     return AdvanceRootDir();
  1692.                 }
  1693.                
  1694.                 UpdateCurrent();
  1695.             }
  1696.            
  1697.             return true;
  1698.         }
  1699.        
  1700.        
  1701.         [ResourceExposure(ResourceScope.None)]
  1702.         // Scoping should be done when opening isolated storage.
  1703.         [ResourceConsumption(ResourceScope.Machine, ResourceScope.Machine)]
  1704.         private bool AdvanceRootDir()
  1705.         {
  1706.             ++m_nRootDir;
  1707.            
  1708.             if (m_nRootDir >= m_RootDir.Length) {
  1709.                 m_nRootDir = m_RootDir.Length;
  1710.                 // to prevent wrap around
  1711.                 return false;
  1712.                 // We are at the very end.
  1713.             }
  1714.            
  1715.             m_SubDir = Directory.GetDirectories(m_RootDir[m_nRootDir]);
  1716.            
  1717.             if (m_SubDir.Length == 0)
  1718.                 return AdvanceRootDir();
  1719.             // recurse here.
  1720.             m_nSubDir = 0;
  1721.            
  1722.             // Set m_Current
  1723.             UpdateCurrent();
  1724.            
  1725.             return true;
  1726.         }
  1727.        
  1728.         [ResourceExposure(ResourceScope.None)]
  1729.         // Scoping should be done when opening isolated storage.
  1730.         [ResourceConsumption(ResourceScope.Machine, ResourceScope.Machine)]
  1731.         private void UpdateCurrent()
  1732.         {
  1733.             m_Current.Path1 = Path.GetFileName(m_RootDir[m_nRootDir]);
  1734.             m_Current.Path2 = Path.GetFileName(m_SubDir[m_nSubDir]);
  1735.         }
  1736.        
  1737.         public object Current {
  1738.             get {
  1739.                
  1740.                 if (m_fReset) {
  1741.                     throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_EnumNotStarted"));
  1742.                 }
  1743.                 else if (m_nRootDir >= m_RootDir.Length) {
  1744.                     throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_EnumEnded"));
  1745.                 }
  1746.                
  1747.                 return (object)m_Current;
  1748.             }
  1749.         }
  1750.        
  1751.         [ResourceExposure(ResourceScope.None)]
  1752.         // Scoping should be done when opening isolated storage.
  1753.         [ResourceConsumption(ResourceScope.Machine, ResourceScope.Machine)]
  1754.         public void Reset()
  1755.         {
  1756.             m_RootDir = null;
  1757.             m_nRootDir = -1;
  1758.            
  1759.             m_SubDir = null;
  1760.             m_nSubDir = -1;
  1761.            
  1762.             m_Current = new TwoPaths();
  1763.             m_fReset = true;
  1764.            
  1765.             m_RootDir = Directory.GetDirectories(m_Root);
  1766.         }
  1767.     }
  1768. }

Developer Fusion