/3.x/WBFSe3/IO/WbfsDriveInfo.cs
# · C# · 465 lines · 292 code · 84 blank · 89 comment · 53 complexity · ab67143841d8dd70fd6b34621037d448 MD5 · raw file
- //-----------------------------------------------------------------------------------------------------------
- // WBFSSync Project by Omega Frost
- // http://wbfssync.codeplex.com/
- //
- // WBFSSync is Licensed under the terms of the
- // Microsoft Reciprocal License (Ms-RL)
- //-----------------------------------------------------------------------------------------------------------
- using System;
- using System.Collections.Generic;
- using System.Linq;
- using System.Text;
- using System.IO;
- using WBFSe3.Native;
- using System.Runtime.InteropServices;
- using WBFSe3.Wbfs;
-
- namespace WBFSe3.IO
- {
- //-------------------------------------------------------------------------------------------------------
- //
- //-------------------------------------------------------------------------------------------------------
- public delegate void DriveUpdatedDelegate(WbfsDriveInfo sender, WbfsError error);
- public delegate void DriveClosedDelegate(WbfsDriveInfo sender);
-
-
- //-------------------------------------------------------------------------------------------------------
- //
- //-------------------------------------------------------------------------------------------------------
- public class WbfsDriveInfo : FileSystemInfo
- {
- //---------------------------------------------------------------------------------------------------
- //
- //---------------------------------------------------------------------------------------------------
- private static HashSet<uint> FatWbfsDrives = new HashSet<uint>();
- private static WbfsDriveInfo[] Drives = new WbfsDriveInfo[26];
-
-
- //---------------------------------------------------------------------------------------------------
- //
- //---------------------------------------------------------------------------------------------------
- protected String name;
- protected String label;
- protected uint serial;
- protected bool largeFiles;
-
- protected long size;
- protected long used;
- protected long free;
-
- protected bool isReadOnly;
- protected bool isSparse;
- protected bool isFixed;
- protected bool isCd;
- protected bool isWbfs;
- protected bool isFatWbfs;
-
- protected bool isReady;
- protected bool isGame;
-
- protected int error;
-
-
- //---------------------------------------------------------------------------------------------------
- //
- //---------------------------------------------------------------------------------------------------
- public event DriveUpdatedDelegate DriveUpdated;
- public event DriveClosedDelegate DriveClosed;
-
-
- //---------------------------------------------------------------------------------------------------
- //
- //---------------------------------------------------------------------------------------------------
- public override String Name { get { return this.name; } }
- public override string FullName { get { return this.name; } }
-
- public String Label { get { return this.label; } set { SetLabel(value); } }
- public uint Serial { get { return this.serial; } }
- public Boolean LargeFiles { get { return this.largeFiles; } }
-
- public long Size { get { lock (this) { ParseSpace(); } return this.size; } }
- public long Used { get { lock (this) { ParseSpace(); } return this.used; } }
- public long Free { get { lock (this) { ParseSpace(); } return this.free; } }
-
- public Boolean IsReadOnly { get { return this.isReadOnly; } }
- public Boolean IsFatWbfs { get { return FatWbfsDrives.Contains(this.serial); } set { SetFatWbfs(value); } }
- public Boolean IsSparse { get { return this.isSparse; } }
- public Boolean IsFixed { get { return this.isFixed; } }
- public Boolean IsWbfs { get { return this.isWbfs; } }
- public Boolean IsCd { get { return this.isCd; } }
-
- public Boolean IsReady { get { return this.isReady; } }
- public Boolean IsGame { get { return this.isGame; } }
- public override bool Exists { get { return true; } }
-
- public Boolean IsValid { get { return this.error != 0; } }
- public int Error { get { return this.error; } }
-
-
- //---------------------------------------------------------------------------------------------------
- //
- //---------------------------------------------------------------------------------------------------
- public static void AddFatWbfsSN(uint sn)
- {
- if (!FatWbfsDrives.Contains(sn))
- FatWbfsDrives.Add(sn);
- }
-
-
- //---------------------------------------------------------------------------------------------------
- //
- //---------------------------------------------------------------------------------------------------
- public static uint[] GetFatWbfsSNs()
- {
- return FatWbfsDrives.ToArray();
- }
-
- //---------------------------------------------------------------------------------------------------
- //
- //---------------------------------------------------------------------------------------------------
- public static WbfsError GetDrive(String path, out WbfsDriveInfo drive)
- {
- WbfsDriveInfo di;
- char letter;
- int error;
- drive = null;
-
- // Path verification
- if (String.IsNullOrEmpty(path))
- return WbfsError.DriveNotFound;
-
- // Get the drive letter
- letter = Path.GetFullPath(path).ToUpper()[0];
-
- // Return already created file
- di = Drives[(int)(letter - 'A')];
- if (di != null)
- {
- if ((error = (int)di.Update()) != 0)
- {
- drive = di;
- Drives[(int)(letter - 'A')] = null;
- return (WbfsError)error;
- }
-
- drive = di;
- return WbfsError.Ok;
- }
-
- // Create new instance of a drive info
- di = new WbfsDriveInfo();
- di.name = letter + ":\\";
-
- // Is drive type supported?
- if (di.ParseType() != 0)
- return WbfsError.DriveNotSupported;
-
- // Check for a known filesystem
- if ((error = di.ParseVolume()) == 0)
- {
- //Calculate space
- if ((error = di.ParseSpace()) != 0)
- return (WbfsError)error;
- }
- else if (!di.isCd) //CD Drives just sucks...
- {
- if (error == 1005)
- {
- //Maybe wbfs drive or game
- if (di.isCd)
- {
- if (di.isReady)
- {
- //Try build the DVD as a game
- }
- }
- else
- {
- //Try open a wbfs device
- WbfsDevice wdi;
- error = (int)WbfsDevice.Open(di.name,
- FileAccess.ReadWrite, false, out wdi);
-
- if (error == 0)
- {
- di = wdi;
- }
- }
- }
- else if (error != 21)
- {
- return (WbfsError)error;
- }
- }
-
- Drives[(int)(letter - 'A')] = di;
- drive = di;
- return WbfsError.Ok;
- }
-
-
- //---------------------------------------------------------------------------------------------------
- //
- //---------------------------------------------------------------------------------------------------
- internal static void InvalidateDrive(Char drive)
- {
- int old = (int)(Char.ToUpper(drive) - 'A');
- Drives[old].OnDriveClosed();
- Drives[old] = null;
- }
-
-
- //---------------------------------------------------------------------------------------------------
- //
- //---------------------------------------------------------------------------------------------------
- internal static void UpdateDrive(WbfsDriveInfo drive)
- {
- int old = (int)(Char.ToUpper(drive.name[0]) - 'A');
-
- drive.DriveClosed = Drives[old].DriveClosed;
- drive.DriveUpdated = Drives[old].DriveUpdated;
- Drives[old] = drive;
-
- drive.OnDriveUpdated(WbfsError.DriveReplace);
- }
-
-
- //---------------------------------------------------------------------------------------------------
- //
- //---------------------------------------------------------------------------------------------------
- protected int ParseType()
- {
- // Get the drive type
- uint type = WbfsNative.GetDriveType(this.name);
-
- switch (type)
- {
- case 2: //Removable
- this.isFixed = false;
- this.isCd = false;
- break;
-
- case 3: //Fixed
- this.isFixed = true;
- this.isCd = false;
- break;
-
- case 5: //CD
- this.isFixed = true;
- this.isCd = true;
- break;
-
- default: //Not Supported
- return -1;
- }
-
- return 0;
- }
-
-
- //---------------------------------------------------------------------------------------------------
- //
- //---------------------------------------------------------------------------------------------------
- private int ParseVolume()
- {
- // Get the volume information
-
- EFileSystemFeature volFeatures;
- StringBuilder volName = new StringBuilder(261);
- StringBuilder volFs = new StringBuilder(261);
-
- uint volSn;
- uint volMaxFile;
-
- this.isReady = WbfsNative.GetVolumeInformation(this.name, volName,
- 261, out volSn, out volMaxFile, out volFeatures, volFs, 261);
-
- if (this.isReady)
- {
- this.serial = volSn;
- this.label = volName.ToString();
- this.isSparse = volFeatures.HasFlag(EFileSystemFeature.SupportsSparseFiles);
- this.isReadOnly = volFeatures.HasFlag(EFileSystemFeature.ReadOnlyVolume);
-
- if ((volName.ToString() == "FAT32") || (volName.ToString() == "FAT"))
- this.largeFiles = false;
- else this.largeFiles = true;
-
- return 0;
- }
- else
- {
- return Marshal.GetLastWin32Error();
- }
-
- }
-
-
- //---------------------------------------------------------------------------------------------------
- //
- //---------------------------------------------------------------------------------------------------
- protected virtual int ParseSpace()
- {
- if (!this.isReady)
- return 0;
-
- ulong volFree, volTotal, volDummy;
- if (!WbfsNative.GetDiskFreeSpaceEx(this.name,
- out volFree, out volTotal, out volDummy))
- {
- return Marshal.GetLastWin32Error();
- }
-
- this.size = (long)volTotal;
- this.free = (long)volFree;
- this.used = (long)(volTotal - volFree);
-
- return 0;
- }
-
-
- //---------------------------------------------------------------------------------------------------
- //
- //---------------------------------------------------------------------------------------------------
- protected WbfsDriveInfo()
- {
- this.name = null;
- this.label = null;
- this.serial = 0;
-
- this.size = 0;
- this.used = 0;
- this.free = 0;
-
- this.isReadOnly = false;
- this.isSparse = false;
- this.isFixed = false;
- this.isCd = false;
- this.isWbfs = false;
- this.isFatWbfs = false;
-
- this.isReady = false;
- this.isGame = false;
- }
-
-
- //---------------------------------------------------------------------------------------------------
- //
- //---------------------------------------------------------------------------------------------------
- protected virtual void SetLabel(String value)
- {
- if (!WbfsNative.SetVolumeLabel(this.name, value))
- {
- int error = Marshal.GetLastWin32Error();
- switch (error)
- {
- default: throw new WbfsIOException(error);
- case 5: throw new UnauthorizedAccessException();
- }
- }
- else
- {
- this.label = value;
- }
- }
-
-
- //---------------------------------------------------------------------------------------------------
- //
- //---------------------------------------------------------------------------------------------------
- protected void SetFatWbfs(Boolean value)
- {
- if (this.isWbfs || this.isCd || !this.isReady)
- return;
-
- lock (FatWbfsDrives)
- {
- if (value) FatWbfsDrives.Add(this.serial);
- else FatWbfsDrives.Remove(this.serial);
- }
- }
-
-
- //---------------------------------------------------------------------------------------------------
- //
- //---------------------------------------------------------------------------------------------------
- public virtual WbfsError Update()
- {
- int error;
- lock (this)
- {
- if ((error = ParseVolume()) == 0)
- error = ParseSpace();
- }
-
- OnDriveUpdated((WbfsError)error);
-
- if (error != 0)
- {
- if (this.isCd || (error == 21) || (error == 1005))
- {
- this.isReady = false;
- return WbfsError.Ok;
- }
- else
- {
- OnDriveClosed();
- Drives[(int)(this.name[0] - 'A')] = null;
- }
- }
- else
- {
- this.isReady = true;
- }
-
- return (WbfsError)error;
- }
-
-
- //---------------------------------------------------------------------------------------------------
- //
- //---------------------------------------------------------------------------------------------------
- public new void Refresh()
- {
- Update();
- }
-
-
- //---------------------------------------------------------------------------------------------------
- //
- //---------------------------------------------------------------------------------------------------
- public virtual WbfsError Close()
- {
- return WbfsError.Ok;
- }
-
-
- //---------------------------------------------------------------------------------------------------
- //
- //---------------------------------------------------------------------------------------------------
- public override void Delete()
- {
- // Nops
- }
-
-
- //---------------------------------------------------------------------------------------------------
- //
- //---------------------------------------------------------------------------------------------------
- protected void OnDriveUpdated(WbfsError error)
- {
- if (this.DriveUpdated != null)
- this.DriveUpdated(this, error);
- }
-
-
- //---------------------------------------------------------------------------------------------------
- //
- //---------------------------------------------------------------------------------------------------
- protected void OnDriveClosed()
- {
- if (this.DriveClosed != null)
- this.DriveClosed(this);
- }
- }
- }