// On NetFX FileStream has an internal no arg constructor that we utilize to provide the facade. We don't have access // to internals in CoreFX so we'll do the next best thing and contort ourselves into the SafeFileHandle constructor. // (A path constructor would try and create the requested file and give us two open handles.) // // We only expose our own nested FileStream so the base class having a handle doesn't matter. Passing a new SafeFileHandle // with ownsHandle: false avoids the parent class closing without our knowledge. private IsolatedStorageFileStream(string path, FileMode mode, FileAccess access, FileShare share, int bufferSize, InitialiationData initializationData) : base(new SafeFileHandle(initializationData.NestedStream.SafeFileHandle.DangerousGetHandle(), ownsHandle: false), access, bufferSize) { _isf = initializationData.StorageFile; _givenPath = path; _fullPath = initializationData.FullPath; _fs = initializationData.NestedStream; }
// If IsolatedStorageFile is null, then we default to using a file that is scoped by user, appdomain, and assembly. private static InitialiationData InitializeFileStream(string path, FileMode mode, FileAccess access, FileShare share, int bufferSize, IsolatedStorageFile isf) { if (path == null) throw new ArgumentNullException(nameof(path)); if ((path.Length == 0) || path.Equals(BackSlash)) throw new ArgumentException( SR.IsolatedStorage_Path); bool createdStore = false; if (isf == null) { isf = IsolatedStorageFile.GetUserStoreForDomain(); createdStore = true; } if (isf.Disposed) throw new ObjectDisposedException(null, SR.IsolatedStorage_StoreNotOpen); switch (mode) { case FileMode.CreateNew: // Assume new file case FileMode.Create: // Check for New file & Unreserve case FileMode.OpenOrCreate: // Check for new file case FileMode.Truncate: // Unreserve old file size case FileMode.Append: // Check for new file case FileMode.Open: // Open existing, else exception break; default: throw new ArgumentException(SR.IsolatedStorage_FileOpenMode); } InitialiationData data = new InitialiationData { FullPath = isf.GetFullPath(path), StorageFile = isf }; try { data.NestedStream = new FileStream(data.FullPath, mode, access, share, bufferSize, FileOptions.None); } catch (Exception e) { // Make an attempt to clean up the StorageFile if we created it try { if (createdStore) { data.StorageFile?.Dispose(); } } catch { } // Exception message might leak the IsolatedStorage path. The desktop prevented this by calling an // internal API which made sure that the exception message was scrubbed. However since the innerException // is never returned to the user(GetIsolatedStorageException() does not populate the innerexception // in retail bits we leak the path only under the debugger via IsolatedStorageException._underlyingException which // they can any way look at via IsolatedStorageFile instance as well. throw IsolatedStorageFile.GetIsolatedStorageException(SR.IsolatedStorage_Operation_ISFS, e); } return data; }
// If IsolatedStorageFile is null, then we default to using a file that is scoped by user, appdomain, and assembly. private static InitialiationData InitializeFileStream(string path, FileMode mode, FileAccess access, FileShare share, int bufferSize, IsolatedStorageFile?isf) { if (path == null) { throw new ArgumentNullException(nameof(path)); } if ((path.Length == 0) || path.Equals(BackSlash)) { throw new ArgumentException( SR.IsolatedStorage_Path); } bool createdStore = false; if (isf == null) { isf = IsolatedStorageFile.GetUserStoreForDomain(); createdStore = true; } if (isf.Disposed) { throw new ObjectDisposedException(null, SR.IsolatedStorage_StoreNotOpen); } switch (mode) { case FileMode.CreateNew: // Assume new file case FileMode.Create: // Check for New file & Unreserve case FileMode.OpenOrCreate: // Check for new file case FileMode.Truncate: // Unreserve old file size case FileMode.Append: // Check for new file case FileMode.Open: // Open existing, else exception break; default: throw new ArgumentException(SR.IsolatedStorage_FileOpenMode); } InitialiationData data = new InitialiationData { FullPath = isf.GetFullPath(path), StorageFile = isf }; try { data.NestedStream = new FileStream(data.FullPath, mode, access, share, bufferSize, FileOptions.None); } catch (Exception e) { // Make an attempt to clean up the StorageFile if we created it try { if (createdStore) { data.StorageFile?.Dispose(); } } catch { } // Exception message might leak the IsolatedStorage path. The .NET Framework prevented this by calling an // internal API which made sure that the exception message was scrubbed. However since the innerException // is never returned to the user(GetIsolatedStorageException() does not populate the innerexception // in retail bits we leak the path only under the debugger via IsolatedStorageException._underlyingException which // they can any way look at via IsolatedStorageFile instance as well. throw IsolatedStorageFile.GetIsolatedStorageException(SR.IsolatedStorage_Operation_ISFS, e); } return(data); }
// On .NET Framework FileStream has an internal no arg constructor that we utilize to provide the facade. We don't have access // to internals in .NET Core so we'll do the next best thing and contort ourselves into the SafeFileHandle constructor. // (A path constructor would try and create the requested file and give us two open handles.) // // We only expose our own nested FileStream so the base class having a handle doesn't matter. Passing a new SafeFileHandle // with ownsHandle: false avoids the parent class closing without our knowledge. private IsolatedStorageFileStream(string path, FileMode mode, FileAccess access, FileShare share, int bufferSize, InitialiationData initializationData) : base(new SafeFileHandle(initializationData.NestedStream.SafeFileHandle.DangerousGetHandle(), ownsHandle: false), access, bufferSize) { _isf = initializationData.StorageFile; _givenPath = path; _fullPath = initializationData.FullPath; _fs = initializationData.NestedStream; }