summaryrefslogtreecommitdiff
path: root/src/mscorlib/src/System/IO/IsolatedStorage/IsolatedStorageAccountingInfo.cs
diff options
context:
space:
mode:
Diffstat (limited to 'src/mscorlib/src/System/IO/IsolatedStorage/IsolatedStorageAccountingInfo.cs')
-rw-r--r--src/mscorlib/src/System/IO/IsolatedStorage/IsolatedStorageAccountingInfo.cs232
1 files changed, 232 insertions, 0 deletions
diff --git a/src/mscorlib/src/System/IO/IsolatedStorage/IsolatedStorageAccountingInfo.cs b/src/mscorlib/src/System/IO/IsolatedStorage/IsolatedStorageAccountingInfo.cs
new file mode 100644
index 0000000000..70bf9da92a
--- /dev/null
+++ b/src/mscorlib/src/System/IO/IsolatedStorage/IsolatedStorageAccountingInfo.cs
@@ -0,0 +1,232 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+using System;
+using System.IO;
+using Microsoft.Win32;
+using Microsoft.Win32.SafeHandles;
+using System.Security;
+using System.Security.Permissions;
+using System.Runtime.InteropServices;
+using System.Diagnostics;
+
+namespace System.IO.IsolatedStorage {
+
+ internal class IsolatedStorageAccountingInfo : IDisposable {
+
+ private const string c_QuotaFileName = "quota.dat";
+ private const string c_UsedFileName = "used.dat";
+
+ string m_RootDirectory;
+
+ [SecurityCritical]
+ SafeFileMappingHandle m_QuotaFileMapping;
+ [SecurityCritical]
+ SafeFileMappingHandle m_UsedSizeFileMapping;
+
+ IntPtr m_QuotaView;
+ IntPtr m_UsedSizeView;
+
+ FileStream m_QuotaFileStream;
+ FileStream m_UsedSizeFileStream;
+
+ bool m_Disposed;
+
+ public long Quota {
+
+ [SecurityCritical]
+ get {
+ lock (this) {
+ long value;
+
+ Map();
+ unsafe {
+ value = *((long*)m_QuotaView);
+ }
+ Unmap();
+ return value;
+ }
+ }
+
+ [SecurityCritical]
+ set {
+ lock (this) {
+ Map();
+ unsafe {
+ *((long*)m_QuotaView) = value;
+ }
+ Unmap();
+ }
+ }
+ }
+
+
+ public long UsedSize {
+ [SecurityCritical]
+ get {
+ lock (this) {
+ long value;
+
+ Map();
+ try {
+ unsafe {
+ value = *((long*)m_UsedSizeView);
+ }
+ } finally {
+ Unmap();
+ }
+ return value;
+ }
+ }
+
+ [SecurityCritical]
+ set {
+ lock(this) {
+ Map();
+ try {
+ unsafe {
+ *((long*)m_UsedSizeView) = value;
+ }
+ } finally {
+ Unmap();
+ }
+ }
+ }
+ }
+
+ ~IsolatedStorageAccountingInfo() {
+ Dispose(false);
+ }
+
+ public void Dispose() {
+ Dispose(true);
+ GC.SuppressFinalize(this);
+ }
+
+ [SecuritySafeCritical]
+ public void Dispose(bool disposing) {
+ lock(this) {
+ if (!m_Disposed) {
+ if (disposing) {
+ if (m_QuotaFileStream != null) {
+ m_QuotaFileStream.Dispose();
+ m_QuotaFileStream = null;
+ }
+
+ if (m_UsedSizeFileStream != null) {
+ m_UsedSizeFileStream.Dispose();
+ m_UsedSizeFileStream = null;
+ }
+
+ if (m_QuotaFileMapping != null) {
+ m_QuotaFileMapping.Dispose();
+ m_QuotaFileMapping = null;
+ }
+
+ if (m_UsedSizeFileMapping != null) {
+ m_UsedSizeFileMapping.Dispose();
+ m_UsedSizeFileMapping = null;
+ }
+ }
+
+ if (m_QuotaView != IntPtr.Zero) {
+ Win32Native.UnmapViewOfFile(m_QuotaView);
+ m_QuotaView = IntPtr.Zero;
+ }
+
+ if (m_UsedSizeView != IntPtr.Zero) {
+ Win32Native.UnmapViewOfFile(m_UsedSizeView);
+ m_UsedSizeView = IntPtr.Zero;
+ }
+
+ m_Disposed = true;
+ }
+ }
+ }
+
+ [SecurityCritical]
+ public IsolatedStorageAccountingInfo(string rootDirectory) {
+ m_RootDirectory = rootDirectory;
+ Init();
+ }
+
+ [SecurityCritical]
+ private void Init() {
+ new FileIOPermission(FileIOPermissionAccess.AllAccess, m_RootDirectory).Assert();
+ m_QuotaFileStream = new FileStream(Path.Combine(m_RootDirectory, c_QuotaFileName), FileMode.OpenOrCreate, FileAccess.ReadWrite, FileShare.ReadWrite, FileStream.DefaultBufferSize, FileOptions.None, c_QuotaFileName, false, false, false);
+ m_UsedSizeFileStream = new FileStream(Path.Combine(m_RootDirectory, c_UsedFileName), FileMode.OpenOrCreate, FileAccess.ReadWrite, FileShare.ReadWrite, FileStream.DefaultBufferSize, FileOptions.None, c_UsedFileName, false, false, false);
+
+ if (m_QuotaFileStream.Length < sizeof(long)) {
+ m_QuotaFileStream.Write(BitConverter.GetBytes(IsolatedStorageFile.DefaultQuota), 0, sizeof(long));
+ }
+
+ if (m_UsedSizeFileStream.Length < sizeof(long)) {
+ m_UsedSizeFileStream.Write(BitConverter.GetBytes((long)0), 0, sizeof(long));
+ }
+ }
+
+ [SecurityCritical]
+ private void Map() {
+ if (m_Disposed) {
+ // This can happen in the case where an IsolatedStorageFileStream is used after the underlying IsolatedStorageFile object is disposed.
+ // which we allowed in Silverlight 3. If this is the case, we will rebuild our state.
+ Init();
+ m_Disposed = false;
+ GC.ReRegisterForFinalize(this);
+ }
+
+ if (m_QuotaFileMapping == null || m_QuotaFileMapping.IsInvalid) {
+ m_QuotaFileMapping = Win32Native.CreateFileMapping(m_QuotaFileStream.SafeFileHandle, IntPtr.Zero, Win32Native.PAGE_READWRITE, 0, 0, null);
+
+ if (m_QuotaFileMapping.IsInvalid) {
+ throw Marshal.GetExceptionForHR(Marshal.GetLastWin32Error());
+ }
+ }
+
+ if (m_UsedSizeFileMapping == null || m_UsedSizeFileMapping.IsInvalid) {
+ m_UsedSizeFileMapping = Win32Native.CreateFileMapping(m_UsedSizeFileStream.SafeFileHandle, IntPtr.Zero, Win32Native.PAGE_READWRITE, 0, 0, null);
+
+ if (m_UsedSizeFileMapping.IsInvalid) {
+ throw Marshal.GetExceptionForHR(Marshal.GetLastWin32Error());
+ }
+ }
+
+ m_QuotaView = Win32Native.MapViewOfFile(m_QuotaFileMapping, Win32Native.FILE_MAP_WRITE | Win32Native.FILE_MAP_READ, 0, 0, UIntPtr.Zero);
+
+ if (m_QuotaView == IntPtr.Zero) {
+ throw Marshal.GetExceptionForHR(Marshal.GetLastWin32Error());
+ }
+
+ m_UsedSizeView = Win32Native.MapViewOfFile(m_UsedSizeFileMapping, Win32Native.FILE_MAP_WRITE | Win32Native.FILE_MAP_READ, 0, 0, UIntPtr.Zero);
+
+ if (m_UsedSizeView == IntPtr.Zero) {
+ throw Marshal.GetExceptionForHR(Marshal.GetLastWin32Error());
+ }
+ }
+
+ [SecurityCritical]
+ private void Unmap() {
+ Win32Native.UnmapViewOfFile(m_QuotaView);
+ m_QuotaView = IntPtr.Zero;
+ Win32Native.UnmapViewOfFile(m_UsedSizeView);
+ m_UsedSizeView = IntPtr.Zero;
+ }
+
+ [SecurityCritical]
+ private static bool IsFileValid(string fileName) {
+ return File.UnsafeExists(fileName) && (FileInfo.UnsafeCreateFileInfo(fileName).Length == sizeof(long));
+ }
+
+ [SecurityCritical]
+ public static bool IsAccountingInfoValid(string rootDirectory) {
+ new FileIOPermission(FileIOPermissionAccess.AllAccess, rootDirectory).Assert();
+ return IsFileValid(Path.Combine(rootDirectory, c_QuotaFileName)) && IsFileValid(Path.Combine(rootDirectory, c_UsedFileName));
+ }
+
+ [SecurityCritical]
+ public static void RemoveAccountingInfo(string rootDirectory) {
+ new FileIOPermission(FileIOPermissionAccess.AllAccess, rootDirectory).Assert();
+ File.UnsafeDelete(Path.Combine(rootDirectory, c_QuotaFileName));
+ File.UnsafeDelete(Path.Combine(rootDirectory, c_UsedFileName));
+ }
+ }
+} \ No newline at end of file