PageRenderTime 23ms CodeModel.GetById 29ms RepoModel.GetById 1ms app.codeStats 0ms

/XamlImageConverter/svg2xaml/SharpVectors/SharpVectorConverters/Utils/DirectoryUtils.cs

http://xamlimageconverter.codeplex.com
C# | 225 lines | 175 code | 19 blank | 31 comment | 26 complexity | 528fa427e812e779238cb750291155eb MD5 | raw file
Possible License(s): GPL-3.0, AGPL-1.0, MPL-2.0-no-copyleft-exception, CC-BY-SA-3.0, LGPL-3.0
  1. // This is based on MSDN Magazine article codes by Stephen Toub (stoub@microsoft.com)
  2. // The article is http://msdn.microsoft.com/en-us/magazine/cc163696.aspx
  3. using System;
  4. using System.IO;
  5. using System.Security;
  6. using System.ComponentModel;
  7. using System.Collections.Generic;
  8. using System.Security.Permissions;
  9. using Microsoft.Win32.SafeHandles;
  10. using System.Runtime.InteropServices;
  11. using System.Runtime.ConstrainedExecution;
  12. using ComTypes = System.Runtime.InteropServices.ComTypes;
  13. namespace SharpVectors.Converters.Utils
  14. {
  15. public static class DirectoryUtils
  16. {
  17. private sealed class SafeFindHandle : SafeHandleZeroOrMinusOneIsInvalid
  18. {
  19. [SecurityPermission(SecurityAction.LinkDemand, UnmanagedCode = true)]
  20. private SafeFindHandle() : base(true)
  21. {
  22. }
  23. protected override bool ReleaseHandle()
  24. {
  25. return FindClose(this.handle);
  26. }
  27. [DllImport("kernel32.dll")]
  28. [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
  29. [SuppressUnmanagedCodeSecurity]
  30. private static extern bool FindClose(IntPtr handle);
  31. }
  32. [DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
  33. [SuppressUnmanagedCodeSecurity]
  34. private static extern SafeFindHandle FindFirstFile(string lpFileName, [In, Out, MarshalAs(UnmanagedType.LPStruct)] WIN32_FIND_DATA lpFindFileData);
  35. [DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
  36. [SuppressUnmanagedCodeSecurity]
  37. private static extern bool FindNextFile(SafeFindHandle hndFindFile, [In, Out, MarshalAs(UnmanagedType.LPStruct)] WIN32_FIND_DATA lpFindFileData);
  38. [DllImport("kernel32.dll", SetLastError = true)]
  39. private static extern ErrorModes SetErrorMode(ErrorModes newMode);
  40. [Serializable]
  41. [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
  42. [BestFitMapping(false)]
  43. private class WIN32_FIND_DATA
  44. {
  45. public FileAttributes dwFileAttributes;
  46. public ComTypes.FILETIME ftCreationTime;
  47. public ComTypes.FILETIME ftLastAccessTime;
  48. public ComTypes.FILETIME ftLastWriteTime;
  49. public int nFileSizeHigh;
  50. public int nFileSizeLow;
  51. public int dwReserved0;
  52. public int dwReserved1;
  53. [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 260)]
  54. public string cFileName;
  55. [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 14)]
  56. public string cAlternateFileName;
  57. }
  58. private const int ERROR_FILE_NOT_FOUND = 0x2;
  59. private const int ERROR_ACCESS_DENIED = 0x5;
  60. private const int ERROR_NO_MORE_FILES = 0x12;
  61. [Flags]
  62. private enum ErrorModes
  63. {
  64. /// <summary>Use the system default, which is to display all error dialog boxes.</summary>
  65. Default = 0x0,
  66. /// <summary>
  67. /// The system does not display the critical-error-handler message box.
  68. /// Instead, the system sends the error to the calling process.
  69. /// </summary>
  70. FailCriticalErrors = 0x1,
  71. /// <summary>
  72. /// 64-bit Windows: The system automatically fixes memory alignment faults and makes them
  73. /// invisible to the application. It does this for the calling process and any descendant processes.
  74. /// After this value is set for a process, subsequent attempts to clear the value are ignored.
  75. /// </summary>
  76. NoGpFaultErrorBox = 0x2,
  77. /// <summary>
  78. /// The system does not display the general-protection-fault message box.
  79. /// This flag should only be set by debugging applications that handle general
  80. /// protection (GP) faults themselves with an exception handler.
  81. /// </summary>
  82. NoAlignmentFaultExcept = 0x4,
  83. /// <summary>
  84. /// The system does not display a message box when it fails to find a file.
  85. /// Instead, the error is returned to the calling process.
  86. /// </summary>
  87. NoOpenFileErrorBox = 0x8000
  88. }
  89. public static void DeleteDirectory(string directoryPath, bool recursive)
  90. {
  91. if (String.IsNullOrEmpty(directoryPath))
  92. {
  93. return;
  94. }
  95. DirectoryInfo dirInfo = new DirectoryInfo(directoryPath);
  96. if (dirInfo.Exists)
  97. {
  98. // It is a directory...
  99. try
  100. {
  101. dirInfo.Attributes = FileAttributes.Normal;
  102. dirInfo.Delete(recursive);
  103. }
  104. catch (UnauthorizedAccessException)
  105. {
  106. // One possible cause of this is read-only file, so first
  107. // try another method of deleting the directory...
  108. foreach (string file in DirectoryUtils.FindFiles(dirInfo, "*.*",
  109. recursive ? SearchOption.AllDirectories : SearchOption.TopDirectoryOnly))
  110. {
  111. File.SetAttributes(file, FileAttributes.Normal);
  112. File.Delete(file);
  113. }
  114. dirInfo.Delete(recursive);
  115. }
  116. }
  117. }
  118. public static IEnumerable<string> FindFiles(DirectoryInfo dir,
  119. string pattern, SearchOption searchOption)
  120. {
  121. // We suppressed this demand for each p/invoke call, so demand it upfront once
  122. new SecurityPermission(SecurityPermissionFlag.UnmanagedCode).Demand();
  123. // Validate parameters
  124. if (dir == null)
  125. throw new ArgumentNullException("dir");
  126. if (pattern == null)
  127. throw new ArgumentNullException("pattern");
  128. // Setup
  129. WIN32_FIND_DATA findData = new WIN32_FIND_DATA();
  130. Stack<DirectoryInfo> directories = new Stack<DirectoryInfo>();
  131. directories.Push(dir);
  132. // Process each directory
  133. ErrorModes origErrorMode = SetErrorMode(ErrorModes.FailCriticalErrors);
  134. try
  135. {
  136. while (directories.Count > 0)
  137. {
  138. // Get the name of the next directory and the corresponding search pattern
  139. dir = directories.Pop();
  140. string dirPath = dir.FullName.Trim();
  141. if (dirPath.Length == 0)
  142. continue;
  143. char lastChar = dirPath[dirPath.Length - 1];
  144. if (lastChar != Path.DirectorySeparatorChar &&
  145. lastChar != Path.AltDirectorySeparatorChar)
  146. {
  147. dirPath += Path.DirectorySeparatorChar;
  148. }
  149. // Process all files in that directory
  150. SafeFindHandle handle = FindFirstFile(dirPath + pattern, findData);
  151. if (handle.IsInvalid)
  152. {
  153. int error = Marshal.GetLastWin32Error();
  154. if (error == ERROR_ACCESS_DENIED ||
  155. error == ERROR_FILE_NOT_FOUND)
  156. {
  157. continue;
  158. }
  159. else
  160. {
  161. throw new Win32Exception(error);
  162. }
  163. }
  164. else
  165. {
  166. try
  167. {
  168. do
  169. {
  170. if ((findData.dwFileAttributes &
  171. FileAttributes.Directory) == 0)
  172. yield return (dirPath + findData.cFileName);
  173. }
  174. while (FindNextFile(handle, findData));
  175. int error = Marshal.GetLastWin32Error();
  176. if (error != ERROR_NO_MORE_FILES)
  177. {
  178. throw new Win32Exception(error);
  179. }
  180. }
  181. finally
  182. {
  183. handle.Dispose();
  184. }
  185. }
  186. // Add all child directories if that's what the user wants
  187. if (searchOption == SearchOption.AllDirectories)
  188. {
  189. foreach (DirectoryInfo childDir in dir.GetDirectories())
  190. {
  191. if ((File.GetAttributes(childDir.FullName) &
  192. FileAttributes.ReparsePoint) == 0)
  193. {
  194. directories.Push(childDir);
  195. }
  196. }
  197. }
  198. }
  199. }
  200. finally
  201. {
  202. SetErrorMode(origErrorMode);
  203. }
  204. }
  205. }
  206. }