WindowsVolumeManager.cs 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119
  1. /* Copyright (C) 2014 Tal Aloni <tal.aloni.il@gmail.com>. All rights reserved.
  2. *
  3. * You can redistribute this program and/or modify it under the terms of
  4. * the GNU Lesser Public License as published by the Free Software Foundation,
  5. * either version 3 of the License, or (at your option) any later version.
  6. */
  7. using System;
  8. using System.Collections.Generic;
  9. using System.IO;
  10. using System.Text;
  11. using Microsoft.Win32.SafeHandles;
  12. using Utilities;
  13. using DiskAccessLibrary.LogicalDiskManager;
  14. namespace DiskAccessLibrary
  15. {
  16. public class WindowsVolumeManager
  17. {
  18. public static bool ExclusiveLockIfMounted(Guid windowsVolumeGuid)
  19. {
  20. return ExclusiveLockIfMounted(windowsVolumeGuid, FileAccess.ReadWrite);
  21. }
  22. public static bool ExclusiveLockIfMounted(Guid windowsVolumeGuid, FileAccess fileAccess)
  23. {
  24. if (IsMounted(windowsVolumeGuid))
  25. {
  26. return ExclusiveLock(windowsVolumeGuid, fileAccess);
  27. }
  28. else
  29. {
  30. return true;
  31. }
  32. }
  33. public static bool ExclusiveLock(Guid windowsVolumeGuid)
  34. {
  35. return ExclusiveLock(windowsVolumeGuid, FileAccess.ReadWrite);
  36. }
  37. /// <summary>
  38. /// Windows will flush all cached data to the volume before locking it.
  39. /// Note: we can only lock a dynamic volume if the disk is online.
  40. /// </summary>
  41. /// <returns>True if a new lock has been obtained</returns>
  42. public static bool ExclusiveLock(Guid windowsVolumeGuid, FileAccess fileAccess)
  43. {
  44. bool newAllocation;
  45. // Windows Vista / 7: Valid handle cannot be obtained for a dynamic volume using ShareMode.ReadWrite.
  46. // The FSCTL_LOCK_VOLUME documentation demands ShareMode.ReadWrite, but ShareMode.None or ShareMode.Write will work too.
  47. SafeFileHandle handle = VolumeHandlePool.ObtainHandle(windowsVolumeGuid, fileAccess, ShareMode.None, out newAllocation);
  48. if (newAllocation)
  49. {
  50. if (!handle.IsInvalid)
  51. {
  52. bool success = VolumeUtils.LockVolume(handle);
  53. if (!success)
  54. {
  55. VolumeHandlePool.ReleaseHandle(windowsVolumeGuid);
  56. }
  57. return success;
  58. }
  59. else
  60. {
  61. VolumeHandlePool.ReleaseHandle(windowsVolumeGuid);
  62. return false;
  63. }
  64. }
  65. else
  66. {
  67. return false;
  68. }
  69. }
  70. /// <summary>
  71. /// Note that the volume will be remounted again on first access.
  72. /// </summary>
  73. public static bool DismountVolume(Guid windowsVolumeGuid)
  74. {
  75. bool releaseHandle;
  76. SafeFileHandle handle = VolumeHandlePool.ObtainHandle(windowsVolumeGuid, FileAccess.ReadWrite, ShareMode.ReadWrite, out releaseHandle);
  77. bool success = false;
  78. if (!handle.IsInvalid)
  79. {
  80. success = VolumeUtils.DismountVolume(handle);
  81. }
  82. if (releaseHandle) // new allocation
  83. {
  84. VolumeHandlePool.ReleaseHandle(windowsVolumeGuid);
  85. }
  86. return success;
  87. }
  88. public static bool ReleaseLock(Guid windowsVolumeGuid)
  89. {
  90. return VolumeHandlePool.ReleaseHandle(windowsVolumeGuid);
  91. }
  92. public static bool IsMounted(Guid windowsVolumeGuid)
  93. {
  94. return VolumeUtils.IsVolumeMounted(windowsVolumeGuid);
  95. }
  96. public static List<string> GetMountPoints(Guid windowsVolumeGuid)
  97. {
  98. return VolumeUtils.GetVolumeMountPoints(windowsVolumeGuid);
  99. }
  100. /// <summary>
  101. /// A volume can be mounted by the OS even if it has no mount points
  102. /// </summary>
  103. public static bool HasMountPoints(Guid windowsVolumeGuid)
  104. {
  105. return (GetMountPoints(windowsVolumeGuid).Count > 0);
  106. }
  107. }
  108. }