@@ -0,0 +1,63 @@ | |||
############################################################################### | |||
# Set default behavior to automatically normalize line endings. | |||
############################################################################### | |||
* text=auto | |||
############################################################################### | |||
# Set default behavior for command prompt diff. | |||
# | |||
# This is need for earlier builds of msysgit that does not have it on by | |||
# default for csharp files. | |||
# Note: This is only used by command line | |||
############################################################################### | |||
#*.cs diff=csharp | |||
############################################################################### | |||
# Set the merge driver for project and solution files | |||
# | |||
# Merging from the command prompt will add diff markers to the files if there | |||
# are conflicts (Merging from VS is not affected by the settings below, in VS | |||
# the diff markers are never inserted). Diff markers may cause the following | |||
# file extensions to fail to load in VS. An alternative would be to treat | |||
# these files as binary and thus will always conflict and require user | |||
# intervention with every merge. To do so, just uncomment the entries below | |||
############################################################################### | |||
#*.sln merge=binary | |||
#*.csproj merge=binary | |||
#*.vbproj merge=binary | |||
#*.vcxproj merge=binary | |||
#*.vcproj merge=binary | |||
#*.dbproj merge=binary | |||
#*.fsproj merge=binary | |||
#*.lsproj merge=binary | |||
#*.wixproj merge=binary | |||
#*.modelproj merge=binary | |||
#*.sqlproj merge=binary | |||
#*.wwaproj merge=binary | |||
############################################################################### | |||
# behavior for image files | |||
# | |||
# image files are treated as binary by default. | |||
############################################################################### | |||
#*.jpg binary | |||
#*.png binary | |||
#*.gif binary | |||
############################################################################### | |||
# diff behavior for common document formats | |||
# | |||
# Convert binary document formats to text before diffing them. This feature | |||
# is only available from the command line. Turn it on by uncommenting the | |||
# entries below. | |||
############################################################################### | |||
#*.doc diff=astextplain | |||
#*.DOC diff=astextplain | |||
#*.docx diff=astextplain | |||
#*.DOCX diff=astextplain | |||
#*.dot diff=astextplain | |||
#*.DOT diff=astextplain | |||
#*.pdf diff=astextplain | |||
#*.PDF diff=astextplain | |||
#*.rtf diff=astextplain | |||
#*.RTF diff=astextplain |
@@ -0,0 +1,245 @@ | |||
## Ignore Visual Studio temporary files, build results, and | |||
## files generated by popular Visual Studio add-ons. | |||
# User-specific files | |||
*.suo | |||
*.user | |||
*.userosscache | |||
*.sln.docstates | |||
# User-specific files (MonoDevelop/Xamarin Studio) | |||
*.userprefs | |||
# Build results | |||
[Dd]ebug/ | |||
[Dd]ebugPublic/ | |||
[Rr]elease/ | |||
[Rr]eleases/ | |||
[Xx]64/ | |||
[Xx]86/ | |||
[Bb]uild/ | |||
bld/ | |||
[Bb]in/ | |||
[Oo]bj/ | |||
# Visual Studio 2015 cache/options directory | |||
.vs/ | |||
# Uncomment if you have tasks that create the project's static files in wwwroot | |||
#wwwroot/ | |||
# MSTest test Results | |||
[Tt]est[Rr]esult*/ | |||
[Bb]uild[Ll]og.* | |||
# NUNIT | |||
*.VisualState.xml | |||
TestResult.xml | |||
# Build Results of an ATL Project | |||
[Dd]ebugPS/ | |||
[Rr]eleasePS/ | |||
dlldata.c | |||
# DNX | |||
project.lock.json | |||
artifacts/ | |||
*_i.c | |||
*_p.c | |||
*_i.h | |||
*.ilk | |||
*.meta | |||
*.obj | |||
*.pch | |||
*.pdb | |||
*.pgc | |||
*.pgd | |||
*.rsp | |||
*.sbr | |||
*.tlb | |||
*.tli | |||
*.tlh | |||
*.tmp | |||
*.tmp_proj | |||
*.log | |||
*.vspscc | |||
*.vssscc | |||
.builds | |||
*.pidb | |||
*.svclog | |||
*.scc | |||
# Chutzpah Test files | |||
_Chutzpah* | |||
# Visual C++ cache files | |||
ipch/ | |||
*.aps | |||
*.ncb | |||
*.opendb | |||
*.opensdf | |||
*.sdf | |||
*.cachefile | |||
*.VC.db | |||
# Visual Studio profiler | |||
*.psess | |||
*.vsp | |||
*.vspx | |||
*.sap | |||
# TFS 2012 Local Workspace | |||
$tf/ | |||
# Guidance Automation Toolkit | |||
*.gpState | |||
# ReSharper is a .NET coding add-in | |||
_ReSharper*/ | |||
*.[Rr]e[Ss]harper | |||
*.DotSettings.user | |||
# JustCode is a .NET coding add-in | |||
.JustCode | |||
# TeamCity is a build add-in | |||
_TeamCity* | |||
# DotCover is a Code Coverage Tool | |||
*.dotCover | |||
# NCrunch | |||
_NCrunch_* | |||
.*crunch*.local.xml | |||
nCrunchTemp_* | |||
# MightyMoose | |||
*.mm.* | |||
AutoTest.Net/ | |||
# Web workbench (sass) | |||
.sass-cache/ | |||
# Installshield output folder | |||
[Ee]xpress/ | |||
# DocProject is a documentation generator add-in | |||
DocProject/buildhelp/ | |||
DocProject/Help/*.HxT | |||
DocProject/Help/*.HxC | |||
DocProject/Help/*.hhc | |||
DocProject/Help/*.hhk | |||
DocProject/Help/*.hhp | |||
DocProject/Help/Html2 | |||
DocProject/Help/html | |||
# Click-Once directory | |||
publish/ | |||
# Publish Web Output | |||
*.[Pp]ublish.xml | |||
*.azurePubxml | |||
# TODO: Un-comment the next line if you do not want to checkin | |||
# your web deploy settings because they may include unencrypted | |||
# passwords | |||
#*.pubxml | |||
*.publishproj | |||
# NuGet Packages | |||
*.nupkg | |||
# The packages folder can be ignored because of Package Restore | |||
**/packages/* | |||
# except build/, which is used as an MSBuild target. | |||
!**/packages/build/ | |||
# Uncomment if necessary however generally it will be regenerated when needed | |||
#!**/packages/repositories.config | |||
# NuGet v3's project.json files produces more ignoreable files | |||
*.nuget.props | |||
*.nuget.targets | |||
# Microsoft Azure Build Output | |||
csx/ | |||
*.build.csdef | |||
# Microsoft Azure Emulator | |||
ecf/ | |||
rcf/ | |||
# Microsoft Azure ApplicationInsights config file | |||
ApplicationInsights.config | |||
# Windows Store app package directory | |||
AppPackages/ | |||
BundleArtifacts/ | |||
# Visual Studio cache files | |||
# files ending in .cache can be ignored | |||
*.[Cc]ache | |||
# but keep track of directories ending in .cache | |||
!*.[Cc]ache/ | |||
# Others | |||
ClientBin/ | |||
[Ss]tyle[Cc]op.* | |||
~$* | |||
*~ | |||
*.dbmdl | |||
*.dbproj.schemaview | |||
*.pfx | |||
*.publishsettings | |||
node_modules/ | |||
orleans.codegen.cs | |||
# RIA/Silverlight projects | |||
Generated_Code/ | |||
# Backup & report files from converting an old project file | |||
# to a newer Visual Studio version. Backup files are not needed, | |||
# because we have git ;-) | |||
_UpgradeReport_Files/ | |||
Backup*/ | |||
UpgradeLog*.XML | |||
UpgradeLog*.htm | |||
# SQL Server files | |||
*.mdf | |||
*.ldf | |||
# Business Intelligence projects | |||
*.rdl.data | |||
*.bim.layout | |||
*.bim_*.settings | |||
# Microsoft Fakes | |||
FakesAssemblies/ | |||
# GhostDoc plugin setting file | |||
*.GhostDoc.xml | |||
# Node.js Tools for Visual Studio | |||
.ntvs_analysis.dat | |||
# Visual Studio 6 build log | |||
*.plg | |||
# Visual Studio 6 workspace options file | |||
*.opt | |||
# Visual Studio LightSwitch build output | |||
**/*.HTMLClient/GeneratedArtifacts | |||
**/*.DesktopClient/GeneratedArtifacts | |||
**/*.DesktopClient/ModelManifest.xml | |||
**/*.Server/GeneratedArtifacts | |||
**/*.Server/ModelManifest.xml | |||
_Pvt_Extensions | |||
# LightSwitch generated files | |||
GeneratedArtifacts/ | |||
ModelManifest.xml | |||
# Paket dependency manager | |||
.paket/paket.exe | |||
# FAKE - F# Make | |||
.fake/ |
@@ -14,7 +14,7 @@ | |||
<AssemblyOriginatorKeyFile>..\AlphaFS.snk</AssemblyOriginatorKeyFile> | |||
<CodeAnalysisRuleSet>AlphaFS.ruleset</CodeAnalysisRuleSet> | |||
<DelaySign>false</DelaySign> | |||
<TargetFrameworkProfile>Client</TargetFrameworkProfile> | |||
<TargetFrameworkProfile /> | |||
</PropertyGroup> | |||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' "> | |||
<DebugSymbols>true</DebugSymbols> | |||
@@ -387,7 +387,7 @@ | |||
--> | |||
<ProjectExtensions> | |||
<VisualStudio> | |||
<UserProperties StartDate="20080813" AssemblyFileVersion="0" AssemblyVersion="0" Reset="1" /> | |||
<UserProperties Reset="1" AssemblyVersion="0" AssemblyFileVersion="0" StartDate="20080813" /> | |||
</VisualStudio> | |||
</ProjectExtensions> | |||
</Project> |
@@ -19,8 +19,6 @@ | |||
* THE SOFTWARE. | |||
*/ | |||
using System.Reflection; | |||
using System.Runtime.CompilerServices; | |||
using System.Runtime.InteropServices; | |||
using System.Resources; | |||
[assembly: AssemblyCompany("")] | |||
@@ -29,7 +27,7 @@ using System.Resources; | |||
[assembly: AssemblyTrademark("")] | |||
[assembly: AssemblyVersion("2.1.0.0")] | |||
[assembly: AssemblyFileVersion("2.1.0.0")] | |||
[assembly: AssemblyFileVersion("2.1.2.0")] | |||
[assembly: AssemblyInformationalVersion("2.0")] | |||
[assembly: NeutralResourcesLanguageAttribute("en-US")] | |||
@@ -19,8 +19,6 @@ | |||
* THE SOFTWARE. | |||
*/ | |||
using System; | |||
namespace Alphaleonis.Win32.Filesystem | |||
{ | |||
/// <summary>Callback used by CopyFileXxx and MoveFileXxx to report progress about the copy/move operation.</summary> | |||
@@ -19,9 +19,6 @@ | |||
* THE SOFTWARE. | |||
*/ | |||
using System.ComponentModel; | |||
using System.Diagnostics.CodeAnalysis; | |||
namespace Alphaleonis.Win32.Filesystem | |||
{ | |||
/// <summary>Class for CopyMoveResult that contains the results for the Copy or Move action.</summary> | |||
@@ -46,15 +43,6 @@ namespace Alphaleonis.Win32.Filesystem | |||
public int ErrorCode { get; internal set; } | |||
/// <summary>The error message from the <see cref="ErrorCode"/> that was encountered during the Copy or Move action.</summary> | |||
/// <value>A message describing the error.</value> | |||
[SuppressMessage("Microsoft.Design", "CA1065:DoNotRaiseExceptionsInUnexpectedLocations")] | |||
public string ErrorMessage | |||
{ | |||
get { return new Win32Exception(ErrorCode).Message; } | |||
} | |||
/// <summary>When true indicates that the Copy or Move action was canceled.</summary> | |||
/// <value><see langword="true"/> when the Copy/Move action was canceled. Otherwise <see langword="false"/>.</value> | |||
public bool IsCanceled { get; internal set; } | |||
@@ -20,6 +20,7 @@ | |||
*/ | |||
using System; | |||
using System.Collections.Generic; | |||
using System.Diagnostics.CodeAnalysis; | |||
using System.IO; | |||
using System.Security; | |||
@@ -804,10 +805,16 @@ namespace Alphaleonis.Win32.Filesystem | |||
var sourcePathLp = sourcePath; | |||
var destinationPathLp = destinationPath; | |||
var skipPathChecks = pathFormat == PathFormat.LongFullPath; | |||
var emulateMove = false; | |||
// Determine Copy or Move action. | |||
var isCopy = File.DetermineIsCopy(copyOptions, moveOptions); | |||
var isMove = !isCopy; | |||
if (!skipPathChecks) | |||
var cmr = copyMoveResult ?? new CopyMoveResult(sourcePath, destinationPath, false, (int) Win32Errors.ERROR_SUCCESS); | |||
if (pathFormat != PathFormat.LongFullPath) | |||
{ | |||
Path.CheckSupportedPathFormat(sourcePathLp, true, true); | |||
Path.CheckSupportedPathFormat(destinationPathLp, true, true); | |||
@@ -825,74 +832,65 @@ namespace Alphaleonis.Win32.Filesystem | |||
// MSDN: .NET3.5+: IOException: The sourceDirName and destDirName parameters refer to the same file or directory. | |||
if (sourcePathLp.Equals(destinationPathLp, StringComparison.OrdinalIgnoreCase)) | |||
NativeError.ThrowException(Win32Errors.ERROR_SAME_DRIVE, destinationPathLp); | |||
} | |||
var emulateMove = false; | |||
// Determine Copy or Move action. | |||
var isCopy = File.DetermineIsCopy(copyOptions, moveOptions); | |||
var isMove = !isCopy; | |||
var cmr = copyMoveResult ?? new CopyMoveResult(sourcePathLp, destinationPathLp, false, (int) Win32Errors.ERROR_SUCCESS); | |||
// Execute once only. | |||
if (!skipPathChecks && isMove) | |||
{ | |||
// Compare the root part of both paths. | |||
var equalRootPaths = Path.GetPathRoot(sourcePathLp, false).Equals(Path.GetPathRoot(destinationPathLp, false), StringComparison.OrdinalIgnoreCase); | |||
// Execute once only. | |||
if (isMove) | |||
{ | |||
// Compare the root part of both paths. | |||
var equalRootPaths = Path.GetPathRoot(sourcePathLp, false).Equals(Path.GetPathRoot(destinationPathLp, false), StringComparison.OrdinalIgnoreCase); | |||
// Method Volume.IsSameVolume() returns true when both paths refer to the same volume, even if one of the paths is a UNC path. | |||
// For example, src = C:\TempSrc and dst = \\localhost\C$\TempDst | |||
var isSameVolume = equalRootPaths || Volume.IsSameVolume(sourcePathLp, destinationPathLp); | |||
// Method Volume.IsSameVolume() returns true when both paths refer to the same volume, even if one of the paths is a UNC path. | |||
// For example, src = C:\TempSrc and dst = \\localhost\C$\TempDst | |||
var isSameVolume = equalRootPaths || Volume.IsSameVolume(sourcePathLp, destinationPathLp); | |||
isMove = isSameVolume && equalRootPaths; | |||
isMove = isSameVolume && equalRootPaths; | |||
if (!isMove) | |||
{ | |||
// A Move() can be emulated by using Copy() and Delete(), but only if the CopyAllowed flag is set. | |||
isMove = ((MoveOptions) moveOptions & MoveOptions.CopyAllowed) != 0; | |||
// MSDN: .NET3.5+: IOException: An attempt was made to move a directory to a different volume. | |||
if (!isMove) | |||
NativeError.ThrowException(Win32Errors.ERROR_NOT_SAME_DEVICE, sourcePathLp, destinationPathLp); | |||
} | |||
{ | |||
// A Move() can be emulated by using Copy() and Delete(), but only if the CopyAllowed flag is set. | |||
isMove = ((MoveOptions) moveOptions & MoveOptions.CopyAllowed) != 0; | |||
// MSDN: .NET3.5+: IOException: An attempt was made to move a directory to a different volume. | |||
if (!isMove) | |||
NativeError.ThrowException(Win32Errors.ERROR_NOT_SAME_DEVICE, sourcePathLp, destinationPathLp); | |||
} | |||
// The NativeMethod.MoveFileXxx() methods fail when: | |||
// - A directory is being moved; | |||
// - One of the paths is a UNC path, even though both paths refer to the same volume. | |||
// For example, src = C:\TempSrc and dst = \\localhost\C$\TempDst | |||
if (isMove) | |||
{ | |||
var srcIsUncPath = Path.IsUncPathCore(sourcePathLp, false, false); | |||
var dstIsUncPath = Path.IsUncPathCore(destinationPathLp, false, false); | |||
isMove = srcIsUncPath && dstIsUncPath; | |||
if (!isMove) | |||
isMove = !srcIsUncPath && !dstIsUncPath; | |||
} | |||
// The NativeMethod.MoveFileXxx() methods fail when: | |||
// - A directory is being moved; | |||
// - One of the paths is a UNC path, even though both paths refer to the same volume. | |||
// For example, src = C:\TempSrc and dst = \\localhost\C$\TempDst | |||
if (isMove) | |||
{ | |||
var srcIsUncPath = Path.IsUncPathCore(sourcePathLp, false, false); | |||
var dstIsUncPath = Path.IsUncPathCore(destinationPathLp, false, false); | |||
isMove = srcIsUncPath && dstIsUncPath; | |||
if (!isMove) | |||
isMove = !srcIsUncPath && !dstIsUncPath; | |||
} | |||
isMove = isMove && isSameVolume && equalRootPaths; | |||
isMove = isMove && isSameVolume && equalRootPaths; | |||
// Emulate Move(). | |||
if (!isMove) | |||
{ | |||
emulateMove = true; | |||
moveOptions = null; | |||
// Emulate Move(). | |||
if (!isMove) | |||
{ | |||
emulateMove = true; | |||
moveOptions = null; | |||
isCopy = true; | |||
copyOptions = CopyOptions.FailIfExists; | |||
isCopy = true; | |||
copyOptions = CopyOptions.FailIfExists; | |||
} | |||
} | |||
} | |||
#endregion // Setup | |||
#region Copy | |||
@@ -900,45 +898,56 @@ namespace Alphaleonis.Win32.Filesystem | |||
{ | |||
CreateDirectoryCore(transaction, destinationPathLp, null, null, false, PathFormat.LongFullPath); | |||
foreach (var fsei in EnumerateFileSystemEntryInfosCore<FileSystemEntryInfo>(transaction, sourcePathLp, Path.WildcardStarMatchAll, DirectoryEnumerationOptions.FilesAndFolders, PathFormat.LongFullPath)) | |||
var dirs = new Queue<string>(1000); | |||
dirs.Enqueue(sourcePathLp); | |||
while (dirs.Count > 0) | |||
{ | |||
var newDestinationPathLp = Path.CombineCore(false, destinationPathLp, fsei.FileName); | |||
cmr = fsei.IsDirectory | |||
? CopyMoveCore(transaction, fsei.LongFullPath, newDestinationPathLp, copyOptions, moveOptions, progressHandler, userProgressData, cmr, PathFormat.LongFullPath) | |||
: File.CopyMoveCore(false, transaction, fsei.LongFullPath, newDestinationPathLp, false, copyOptions, moveOptions, progressHandler, userProgressData, cmr, PathFormat.LongFullPath); | |||
var srcLp = dirs.Dequeue(); | |||
var dstLp = srcLp.Replace(sourcePathLp, destinationPathLp); | |||
if (cmr.ErrorCode == Win32Errors.ERROR_SUCCESS) | |||
foreach (var fsei in EnumerateFileSystemEntryInfosCore<FileSystemEntryInfo>(transaction, srcLp, Path.WildcardStarMatchAll, DirectoryEnumerationOptions.FilesAndFolders, PathFormat.LongFullPath)) | |||
{ | |||
var newDestinationPathLp = Path.CombineCore(false, dstLp, fsei.FileName); | |||
if (fsei.IsDirectory) | |||
{ | |||
CreateDirectoryCore(transaction, newDestinationPathLp, null, null, false, PathFormat.LongFullPath); | |||
dirs.Enqueue(fsei.LongFullPath); | |||
cmr.TotalFolders++; | |||
else | |||
continue; | |||
} | |||
cmr = File.CopyMoveCore(false, transaction, fsei.LongFullPath, newDestinationPathLp, false, copyOptions, moveOptions, progressHandler, userProgressData, cmr, PathFormat.LongFullPath); | |||
if (cmr.ErrorCode == Win32Errors.ERROR_SUCCESS) | |||
{ | |||
cmr.TotalFiles++; | |||
cmr.TotalBytes += fsei.FileSize; | |||
} | |||
// Remove the folder or file when copying was successful. | |||
if (emulateMove) | |||
{ | |||
if (fsei.IsDirectory) | |||
DeleteDirectoryCore(fsei, transaction, null, true, true, true, PathFormat.LongFullPath); | |||
// Remove the folder or file when copying was successful. | |||
if (emulateMove) | |||
{ | |||
if (fsei.IsDirectory) | |||
DeleteDirectoryCore(fsei, transaction, null, true, true, false, true, PathFormat.LongFullPath); | |||
else | |||
File.DeleteFileCore(transaction, fsei.LongFullPath, true, PathFormat.LongFullPath); | |||
else | |||
File.DeleteFileCore(transaction, fsei.LongFullPath, true, PathFormat.LongFullPath); | |||
} | |||
} | |||
} | |||
if (cmr.IsCanceled) | |||
return cmr; | |||
if (cmr.IsCanceled) | |||
return cmr; | |||
} | |||
} | |||
// Remove source folder. | |||
if (emulateMove && cmr.ErrorCode == Win32Errors.ERROR_SUCCESS) | |||
DeleteDirectoryCore(null, transaction, sourcePathLp, true, true, false, true, PathFormat.LongFullPath); | |||
DeleteDirectoryCore(null, transaction, sourcePathLp, true, true, true, PathFormat.LongFullPath); | |||
} | |||
#endregion // Copy | |||
@@ -950,7 +959,7 @@ namespace Alphaleonis.Win32.Filesystem | |||
{ | |||
// MoveOptions.ReplaceExisting: This value cannot be used if lpNewFileName or lpExistingFileName names a directory. | |||
if (((MoveOptions) moveOptions & MoveOptions.ReplaceExisting) != 0) | |||
DeleteDirectoryCore(null, transaction, destinationPathLp, true, true, false, true, PathFormat.LongFullPath); | |||
DeleteDirectoryCore(null, transaction, destinationPathLp, true, true, true, PathFormat.LongFullPath); | |||
// Moves a file or directory, including its children. | |||
@@ -961,7 +970,7 @@ namespace Alphaleonis.Win32.Filesystem | |||
#endregion // Move | |||
return cmr; | |||
return isMove ? null : cmr; | |||
} | |||
#endregion // Internal Methods | |||
@@ -20,6 +20,7 @@ | |||
*/ | |||
using System; | |||
using System.Collections.Generic; | |||
using System.Diagnostics.CodeAnalysis; | |||
using System.Globalization; | |||
using System.IO; | |||
@@ -44,7 +45,7 @@ namespace Alphaleonis.Win32.Filesystem | |||
[SecurityCritical] | |||
public static void Delete(string path) | |||
{ | |||
DeleteDirectoryCore(null, null, path, false, false, true, false, PathFormat.RelativePath); | |||
DeleteDirectoryCore(null, null, path, false, false, false, PathFormat.RelativePath); | |||
} | |||
/// <summary>Deletes the specified directory and, if indicated, any subdirectories in the directory.</summary> | |||
@@ -60,7 +61,7 @@ namespace Alphaleonis.Win32.Filesystem | |||
[SecurityCritical] | |||
public static void Delete(string path, bool recursive) | |||
{ | |||
DeleteDirectoryCore(null, null, path, recursive, false, !recursive, false, PathFormat.RelativePath); | |||
DeleteDirectoryCore(null, null, path, recursive, false, false, PathFormat.RelativePath); | |||
} | |||
#endregion // .NET | |||
@@ -78,11 +79,10 @@ namespace Alphaleonis.Win32.Filesystem | |||
[SecurityCritical] | |||
public static void Delete(string path, PathFormat pathFormat) | |||
{ | |||
DeleteDirectoryCore(null, null, path, false, false, true, false, pathFormat); | |||
DeleteDirectoryCore(null, null, path, false, false, false, pathFormat); | |||
} | |||
/// <summary>[AlphaFS] Deletes the specified directory and, if indicated, any subdirectories in the directory.</summary> | |||
/// <exception cref="ArgumentException"/> | |||
/// <exception cref="ArgumentNullException"/> | |||
@@ -97,11 +97,10 @@ namespace Alphaleonis.Win32.Filesystem | |||
[SecurityCritical] | |||
public static void Delete(string path, bool recursive, PathFormat pathFormat) | |||
{ | |||
DeleteDirectoryCore(null, null, path, recursive, false, !recursive, false, pathFormat); | |||
DeleteDirectoryCore(null, null, path, recursive, false, false, pathFormat); | |||
} | |||
/// <summary>[AlphaFS] Deletes the specified directory and, if indicated, any subdirectories in the directory.</summary> | |||
/// <exception cref="ArgumentException"/> | |||
/// <exception cref="ArgumentNullException"/> | |||
@@ -116,7 +115,7 @@ namespace Alphaleonis.Win32.Filesystem | |||
[SecurityCritical] | |||
public static void Delete(string path, bool recursive, bool ignoreReadOnly) | |||
{ | |||
DeleteDirectoryCore(null, null, path, recursive, ignoreReadOnly, !recursive, false, PathFormat.RelativePath); | |||
DeleteDirectoryCore(null, null, path, recursive, ignoreReadOnly, false, PathFormat.RelativePath); | |||
} | |||
/// <summary>[AlphaFS] Deletes the specified directory and, if indicated, any subdirectories in the directory.</summary> | |||
@@ -134,9 +133,10 @@ namespace Alphaleonis.Win32.Filesystem | |||
[SecurityCritical] | |||
public static void Delete(string path, bool recursive, bool ignoreReadOnly, PathFormat pathFormat) | |||
{ | |||
DeleteDirectoryCore(null, null, path, recursive, ignoreReadOnly, !recursive, false, pathFormat); | |||
DeleteDirectoryCore(null, null, path, recursive, ignoreReadOnly, false, pathFormat); | |||
} | |||
#region Transactional | |||
/// <summary>[AlphaFS] Deletes an empty directory from a specified path.</summary> | |||
@@ -152,7 +152,7 @@ namespace Alphaleonis.Win32.Filesystem | |||
[SecurityCritical] | |||
public static void DeleteTransacted(KernelTransaction transaction, string path) | |||
{ | |||
DeleteDirectoryCore(null, transaction, path, false, false, true, false, PathFormat.RelativePath); | |||
DeleteDirectoryCore(null, transaction, path, false, false, false, PathFormat.RelativePath); | |||
} | |||
/// <summary>[AlphaFS] Deletes an empty directory from a specified path.</summary> | |||
@@ -169,11 +169,10 @@ namespace Alphaleonis.Win32.Filesystem | |||
[SecurityCritical] | |||
public static void DeleteTransacted(KernelTransaction transaction, string path, PathFormat pathFormat) | |||
{ | |||
DeleteDirectoryCore(null, transaction, path, false, false, true, false, pathFormat); | |||
DeleteDirectoryCore(null, transaction, path, false, false, false, pathFormat); | |||
} | |||
/// <summary>[AlphaFS] Deletes the specified directory and, if indicated, any subdirectories in the directory.</summary> | |||
/// <exception cref="ArgumentException"/> | |||
/// <exception cref="ArgumentNullException"/> | |||
@@ -188,7 +187,7 @@ namespace Alphaleonis.Win32.Filesystem | |||
[SecurityCritical] | |||
public static void DeleteTransacted(KernelTransaction transaction, string path, bool recursive) | |||
{ | |||
DeleteDirectoryCore(null, transaction, path, recursive, false, !recursive, false, PathFormat.RelativePath); | |||
DeleteDirectoryCore(null, transaction, path, recursive, false, false, PathFormat.RelativePath); | |||
} | |||
/// <summary>[AlphaFS] Deletes the specified directory and, if indicated, any subdirectories in the directory.</summary> | |||
@@ -206,10 +205,9 @@ namespace Alphaleonis.Win32.Filesystem | |||
[SecurityCritical] | |||
public static void DeleteTransacted(KernelTransaction transaction, string path, bool recursive, PathFormat pathFormat) | |||
{ | |||
DeleteDirectoryCore(null, transaction, path, recursive, false, !recursive, false, pathFormat); | |||
DeleteDirectoryCore(null, transaction, path, recursive, false, false, pathFormat); | |||
} | |||
/// <summary>[AlphaFS] Deletes the specified directory and, if indicated, any subdirectories in the directory.</summary> | |||
/// <exception cref="ArgumentException"/> | |||
@@ -226,7 +224,7 @@ namespace Alphaleonis.Win32.Filesystem | |||
[SecurityCritical] | |||
public static void DeleteTransacted(KernelTransaction transaction, string path, bool recursive, bool ignoreReadOnly) | |||
{ | |||
DeleteDirectoryCore(null, transaction, path, recursive, ignoreReadOnly, !recursive, false, PathFormat.RelativePath); | |||
DeleteDirectoryCore(null, transaction, path, recursive, ignoreReadOnly, false, PathFormat.RelativePath); | |||
} | |||
/// <summary>[AlphaFS] Deletes the specified directory and, if indicated, any subdirectories in the directory.</summary> | |||
@@ -245,11 +243,12 @@ namespace Alphaleonis.Win32.Filesystem | |||
[SecurityCritical] | |||
public static void DeleteTransacted(KernelTransaction transaction, string path, bool recursive, bool ignoreReadOnly, PathFormat pathFormat) | |||
{ | |||
DeleteDirectoryCore(null, transaction, path, recursive, ignoreReadOnly, !recursive, false, pathFormat); | |||
DeleteDirectoryCore(null, transaction, path, recursive, ignoreReadOnly, false, pathFormat); | |||
} | |||
#endregion // Transactional | |||
#region Internal Methods | |||
/// <summary>Deletes the specified directory and, if indicated, any subdirectories in the directory.</summary> | |||
@@ -261,76 +260,81 @@ namespace Alphaleonis.Win32.Filesystem | |||
/// <exception cref="NotSupportedException"/> | |||
/// <exception cref="UnauthorizedAccessException"/> | |||
/// <exception cref="DirectoryReadOnlyException"/> | |||
/// <param name="fileSystemEntryInfo">A FileSystemEntryInfo instance. Use either <paramref name="fileSystemEntryInfo"/> or <paramref name="path"/>, not both.</param> | |||
/// <param name="fsEntryInfo">A FileSystemEntryInfo instance. Use either <paramref name="fsEntryInfo"/> or <paramref name="path"/>, not both.</param> | |||
/// <param name="transaction">The transaction.</param> | |||
/// <param name="path">The name of the directory to remove. Use either <paramref name="path"/> or <paramref name="fileSystemEntryInfo"/>, not both.</param> | |||
/// <param name="path">The name of the directory to remove. Use either <paramref name="path"/> or <paramref name="fsEntryInfo"/>, not both.</param> | |||
/// <param name="recursive"><see langword="true"/> to remove all files and subdirectories recursively; <see langword="false"/> otherwise only the top level empty directory.</param> | |||
/// <param name="ignoreReadOnly"><see langword="true"/> overrides read only attribute of files and directories.</param> | |||
/// <param name="requireEmpty"><see langword="true"/> requires the directory must be empty.</param> | |||
/// <param name="continueOnNotExist"><see langword="true"/> does not throw an Exception when the file system object does not exist.</param> | |||
/// <param name="continueOnNotFound">When <see langword="true"/> does not throw an Exception when the directory does not exist.</param> | |||
/// <param name="pathFormat">Indicates the format of the path parameter(s).</param> | |||
[SuppressMessage("Microsoft.Maintainability", "CA1502:AvoidExcessiveComplexity")] | |||
[SecurityCritical] | |||
internal static void DeleteDirectoryCore(FileSystemEntryInfo fileSystemEntryInfo, KernelTransaction transaction, string path, bool recursive, bool ignoreReadOnly, bool requireEmpty, bool continueOnNotExist, PathFormat pathFormat) | |||
internal static void DeleteDirectoryCore(FileSystemEntryInfo fsEntryInfo, KernelTransaction transaction, string path, bool recursive, bool ignoreReadOnly, bool continueOnNotFound, PathFormat pathFormat) | |||
{ | |||
#region Setup | |||
if (pathFormat == PathFormat.RelativePath) | |||
Path.CheckSupportedPathFormat(path, true, true); | |||
if (fileSystemEntryInfo == null) | |||
if (fsEntryInfo == null) | |||
{ | |||
// MSDN: .NET 3.5+: DirectoryNotFoundException: | |||
// Path does not exist or could not be found. | |||
// Path refers to a file instead of a directory. | |||
// The specified path is invalid (for example, it is on an unmapped drive). | |||
fileSystemEntryInfo = File.GetFileSystemEntryInfoCore(true, transaction, Path.GetExtendedLengthPathCore(transaction, path, pathFormat, GetFullPathOptions.TrimEnd | GetFullPathOptions.RemoveTrailingDirectorySeparator), continueOnNotExist, pathFormat); | |||
} | |||
if (pathFormat == PathFormat.RelativePath) | |||
Path.CheckSupportedPathFormat(path, true, true); | |||
if (fileSystemEntryInfo == null) | |||
return; | |||
fsEntryInfo = File.GetFileSystemEntryInfoCore(true, transaction, Path.GetExtendedLengthPathCore(transaction, path, pathFormat, GetFullPathOptions.TrimEnd | GetFullPathOptions.RemoveTrailingDirectorySeparator), continueOnNotFound, pathFormat); | |||
string pathLp = fileSystemEntryInfo.LongFullPath; | |||
if (fsEntryInfo == null) | |||
return; | |||
} | |||
#endregion // Setup | |||
// Do not follow mount points nor symbolic links, but do delete the reparse point itself. | |||
// Do not follow mount points nor symbolic links, but do delete the reparse point itself. | |||
// If directory is reparse point, disable recursion. | |||
if (recursive && fileSystemEntryInfo.IsReparsePoint) | |||
recursive = false; | |||
// Check to see if this is a mount point, and unmount it. | |||
if (fileSystemEntryInfo.IsMountPoint) | |||
if (recursive && !fsEntryInfo.IsReparsePoint) | |||
{ | |||
int lastError = Volume.DeleteVolumeMountPointCore(pathLp, true); | |||
if (lastError != Win32Errors.ERROR_SUCCESS && lastError != Win32Errors.ERROR_PATH_NOT_FOUND) | |||
NativeError.ThrowException(lastError, pathLp); | |||
// Now it is safe to delete the actual directory. | |||
} | |||
var dirs = new Stack<string>(1000); | |||
if (recursive) | |||
{ | |||
// Enumerate all file system objects. | |||
foreach (var fsei in EnumerateFileSystemEntryInfosCore<FileSystemEntryInfo>(transaction, pathLp, Path.WildcardStarMatchAll, DirectoryEnumerationOptions.FilesAndFolders, PathFormat.LongFullPath)) | |||
foreach (var fsei in EnumerateFileSystemEntryInfosCore<FileSystemEntryInfo>(transaction, fsEntryInfo.LongFullPath, Path.WildcardStarMatchAll, DirectoryEnumerationOptions.FilesAndFolders | DirectoryEnumerationOptions.Recursive, PathFormat.LongFullPath)) | |||
{ | |||
if (fsei.IsDirectory) | |||
DeleteDirectoryCore(fsei, transaction, null, true, ignoreReadOnly, requireEmpty, true, PathFormat.LongFullPath); | |||
{ | |||
// Check to see if this is a mount point, and unmount it. | |||
// Now it is safe to delete the actual directory. | |||
if (fsei.IsMountPoint) | |||
Volume.DeleteVolumeMountPointCore(fsei.LongFullPath, false); | |||
dirs.Push(fsei.LongFullPath); | |||
} | |||
else | |||
File.DeleteFileCore(transaction, fsei.LongFullPath, ignoreReadOnly, PathFormat.LongFullPath); | |||
} | |||
while (dirs.Count > 0) | |||
DeleteDirectoryCore(transaction, dirs.Pop(), ignoreReadOnly, continueOnNotFound); | |||
} | |||
#region Remove | |||
// Check to see if this is a mount point, and unmount it. | |||
// Now it is safe to delete the actual directory. | |||
if (fsEntryInfo.IsMountPoint) | |||
Volume.DeleteVolumeMountPointCore(fsEntryInfo.LongFullPath, false); | |||
DeleteDirectoryCore(transaction, fsEntryInfo.LongFullPath, ignoreReadOnly, continueOnNotFound); | |||
} | |||
private static void DeleteDirectoryCore(KernelTransaction transaction, string pathLp, bool ignoreReadOnly, bool continueOnNotFound) | |||
{ | |||
startRemoveDirectory: | |||
if (!(transaction == null || !NativeMethods.IsAtLeastWindowsVista | |||
var success = transaction == null || !NativeMethods.IsAtLeastWindowsVista | |||
// RemoveDirectory() / RemoveDirectoryTransacted() | |||
// In the ANSI version of this function, the name is limited to MAX_PATH characters. | |||
@@ -340,17 +344,17 @@ namespace Alphaleonis.Win32.Filesystem | |||
// RemoveDirectory on a symbolic link will remove the link itself. | |||
? NativeMethods.RemoveDirectory(pathLp) | |||
: NativeMethods.RemoveDirectoryTransacted(pathLp, transaction.SafeHandle))) | |||
: NativeMethods.RemoveDirectoryTransacted(pathLp, transaction.SafeHandle); | |||
var lastError = Marshal.GetLastWin32Error(); | |||
if (!success) | |||
{ | |||
int lastError = Marshal.GetLastWin32Error(); | |||
switch ((uint) lastError) | |||
{ | |||
case Win32Errors.ERROR_DIR_NOT_EMPTY: | |||
if (requireEmpty) | |||
// MSDN: .NET 3.5+: IOException: The directory specified by path is not an empty directory. | |||
throw new DirectoryNotEmptyException(pathLp); | |||
goto startRemoveDirectory; | |||
// MSDN: .NET 3.5+: IOException: The directory specified by path is not an empty directory. | |||
throw new DirectoryNotEmptyException(pathLp); | |||
case Win32Errors.ERROR_DIRECTORY: | |||
@@ -361,18 +365,20 @@ namespace Alphaleonis.Win32.Filesystem | |||
case Win32Errors.ERROR_PATH_NOT_FOUND: | |||
if (continueOnNotExist) | |||
if (continueOnNotFound) | |||
return; | |||
break; | |||
case Win32Errors.ERROR_SHARING_VIOLATION: | |||
// MSDN: .NET 3.5+: IOException: The directory is being used by another process or there is an open handle on the directory. | |||
NativeError.ThrowException(lastError, pathLp); | |||
break; | |||
case Win32Errors.ERROR_ACCESS_DENIED: | |||
var data = new NativeMethods.WIN32_FILE_ATTRIBUTE_DATA(); | |||
int dataInitialised = File.FillAttributeInfoCore(transaction, pathLp, ref data, false, true); | |||
var dataInitialised = File.FillAttributeInfoCore(transaction, pathLp, ref data, false, true); | |||
if (data.dwFileAttributes != (FileAttributes) (-1)) | |||
{ | |||
@@ -383,7 +389,7 @@ namespace Alphaleonis.Win32.Filesystem | |||
if (ignoreReadOnly) | |||
{ | |||
// Reset directory attributes. | |||
File.SetAttributesCore(true, transaction, pathLp, FileAttributes.Normal, true, PathFormat.LongFullPath); | |||
File.SetAttributesCore(true, transaction, pathLp, FileAttributes.Normal, PathFormat.LongFullPath); | |||
goto startRemoveDirectory; | |||
} | |||
@@ -392,8 +398,9 @@ namespace Alphaleonis.Win32.Filesystem | |||
} | |||
} | |||
// MSDN: .NET 3.5+: UnauthorizedAccessException: The caller does not have the required permission. | |||
if (dataInitialised == Win32Errors.ERROR_SUCCESS) | |||
// MSDN: .NET 3.5+: UnauthorizedAccessException: The caller does not have the required permission. | |||
NativeError.ThrowException(lastError, pathLp); | |||
break; | |||
@@ -408,8 +415,6 @@ namespace Alphaleonis.Win32.Filesystem | |||
NativeError.ThrowException(lastError, pathLp); | |||
} | |||
#endregion // Remove | |||
} | |||
#endregion // Internal Methods | |||
@@ -20,6 +20,7 @@ | |||
*/ | |||
using System; | |||
using System.Collections.Generic; | |||
using System.Globalization; | |||
using System.IO; | |||
using System.Linq; | |||
@@ -32,47 +33,76 @@ namespace Alphaleonis.Win32.Filesystem | |||
/// <summary>[AlphaFS] Deletes empty subdirectories from the specified directory.</summary> | |||
/// <exception cref="ArgumentException"/> | |||
/// <exception cref="ArgumentNullException"/> | |||
/// <exception cref="DirectoryNotFoundException"/> | |||
/// <exception cref="IOException"/> | |||
/// <exception cref="NotSupportedException"/> | |||
/// <exception cref="UnauthorizedAccessException"/> | |||
/// <exception cref="DirectoryReadOnlyException"/> | |||
/// <param name="path">The name of the directory to remove empty subdirectories from.</param> | |||
[SecurityCritical] | |||
public static void DeleteEmptySubdirectories(string path) | |||
{ | |||
DeleteEmptySubdirectoriesCore(null, null, path, false, false, PathFormat.RelativePath); | |||
} | |||
/// <summary>[AlphaFS] Deletes empty subdirectories from the specified directory.</summary> | |||
/// <exception cref="ArgumentException"/> | |||
/// <exception cref="ArgumentNullException"/> | |||
/// <exception cref="DirectoryNotFoundException"/> | |||
/// <exception cref="IOException"/> | |||
/// <exception cref="NotSupportedException"/> | |||
/// <exception cref="UnauthorizedAccessException"/> | |||
/// <exception cref="DirectoryReadOnlyException"/> | |||
/// <param name="path">The name of the directory to remove empty subdirectories from.</param> | |||
/// <param name="recursive"><see langword="true"/> deletes empty subdirectories from this directory and its subdirectories.</param> | |||
[SecurityCritical] | |||
public static void DeleteEmptySubdirectories(string path, bool recursive) | |||
{ | |||
DeleteEmptySubdirectoriesCore(null, null, path, recursive, false, true, PathFormat.RelativePath); | |||
DeleteEmptySubdirectoriesCore(null, null, path, recursive, false, PathFormat.RelativePath); | |||
} | |||
/// <summary>[AlphaFS] Deletes empty subdirectories from the specified directory.</summary> | |||
/// <exception cref="ArgumentException"/> | |||
/// <exception cref="ArgumentNullException"/> | |||
/// <exception cref="ArgumentNullException"/> | |||
/// <exception cref="DirectoryNotFoundException"/> | |||
/// <exception cref="IOException"/> | |||
/// <exception cref="NotSupportedException"/> | |||
/// <exception cref="UnauthorizedAccessException"/> | |||
/// <exception cref="DirectoryReadOnlyException"/> | |||
/// <param name="path">The name of the directory to remove empty subdirectories from.</param> | |||
/// <param name="recursive"><see langword="true"/> deletes empty subdirectories from this directory and its subdirectories.</param> | |||
/// <param name="pathFormat">Indicates the format of the path parameter(s).</param> | |||
[SecurityCritical] | |||
public static void DeleteEmptySubdirectories(string path, bool recursive, PathFormat pathFormat) | |||
{ | |||
DeleteEmptySubdirectoriesCore(null, null, path, recursive, false, true, pathFormat); | |||
DeleteEmptySubdirectoriesCore(null, null, path, recursive, false, pathFormat); | |||
} | |||
/// <summary>[AlphaFS] Deletes empty subdirectories from the specified directory.</summary> | |||
/// <exception cref="ArgumentException"/> | |||
/// <exception cref="ArgumentNullException"/> | |||
/// <exception cref="ArgumentNullException"/> | |||
/// <exception cref="DirectoryNotFoundException"/> | |||
/// <exception cref="IOException"/> | |||
/// <exception cref="NotSupportedException"/> | |||
/// <exception cref="UnauthorizedAccessException"/> | |||
/// <exception cref="DirectoryReadOnlyException"/> | |||
/// <param name="path">The name of the directory to remove empty subdirectories from.</param> | |||
/// <param name="recursive"><see langword="true"/> deletes empty subdirectories from this directory and its subdirectories.</param> | |||
/// <param name="ignoreReadOnly"><see langword="true"/> overrides read only <see cref="FileAttributes"/> of empty directories.</param> | |||
[SecurityCritical] | |||
public static void DeleteEmptySubdirectories(string path, bool recursive, bool ignoreReadOnly) | |||
{ | |||
DeleteEmptySubdirectoriesCore(null, null, path, recursive, ignoreReadOnly, true, PathFormat.RelativePath); | |||
DeleteEmptySubdirectoriesCore(null, null, path, recursive, ignoreReadOnly, PathFormat.RelativePath); | |||
} | |||
/// <summary>[AlphaFS] Deletes empty subdirectories from the specified directory.</summary> | |||
/// <exception cref="ArgumentException"/> | |||
/// <exception cref="ArgumentNullException"/> | |||
/// <exception cref="ArgumentNullException"/> | |||
/// <exception cref="DirectoryNotFoundException"/> | |||
/// <exception cref="IOException"/> | |||
/// <exception cref="NotSupportedException"/> | |||
/// <exception cref="UnauthorizedAccessException"/> | |||
/// <exception cref="DirectoryReadOnlyException"/> | |||
/// <param name="path">The name of the directory to remove empty subdirectories from.</param> | |||
/// <param name="recursive"><see langword="true"/> deletes empty subdirectories from this directory and its subdirectories.</param> | |||
/// <param name="ignoreReadOnly"><see langword="true"/> overrides read only <see cref="FileAttributes"/> of empty directories.</param> | |||
@@ -80,28 +110,53 @@ namespace Alphaleonis.Win32.Filesystem | |||
[SecurityCritical] | |||
public static void DeleteEmptySubdirectories(string path, bool recursive, bool ignoreReadOnly, PathFormat pathFormat) | |||
{ | |||
DeleteEmptySubdirectoriesCore(null, null, path, recursive, ignoreReadOnly, true, pathFormat); | |||
DeleteEmptySubdirectoriesCore(null, null, path, recursive, ignoreReadOnly, pathFormat); | |||
} | |||
#region Transactional | |||
/// <summary>[AlphaFS] Deletes empty subdirectories from the specified directory.</summary> | |||
/// <exception cref="ArgumentException"/> | |||
/// <exception cref="ArgumentNullException"/> | |||
/// <exception cref="DirectoryNotFoundException"/> | |||
/// <exception cref="IOException"/> | |||
/// <exception cref="NotSupportedException"/> | |||
/// <exception cref="UnauthorizedAccessException"/> | |||
/// <exception cref="DirectoryReadOnlyException"/> | |||
/// <param name="transaction">The transaction.</param> | |||
/// <param name="path">The name of the directory to remove empty subdirectories from.</param> | |||
[SecurityCritical] | |||
public static void DeleteEmptySubdirectoriesTransacted(KernelTransaction transaction, string path) | |||
{ | |||
DeleteEmptySubdirectoriesCore(null, transaction, path, false, false, PathFormat.RelativePath); | |||
} | |||
/// <summary>[AlphaFS] Deletes empty subdirectories from the specified directory.</summary> | |||
/// <exception cref="ArgumentException"/> | |||
/// <exception cref="ArgumentNullException"/> | |||
/// <exception cref="DirectoryNotFoundException"/> | |||
/// <exception cref="IOException"/> | |||
/// <exception cref="NotSupportedException"/> | |||
/// <exception cref="UnauthorizedAccessException"/> | |||
/// <exception cref="DirectoryReadOnlyException"/> | |||
/// <param name="transaction">The transaction.</param> | |||
/// <param name="path">The name of the directory to remove empty subdirectories from.</param> | |||
/// <param name="recursive"><see langword="true"/> deletes empty subdirectories from this directory and its subdirectories.</param> | |||
[SecurityCritical] | |||
public static void DeleteEmptySubdirectoriesTransacted(KernelTransaction transaction, string path, bool recursive) | |||
{ | |||
DeleteEmptySubdirectoriesCore(null, transaction, path, recursive, false, true, PathFormat.RelativePath); | |||
DeleteEmptySubdirectoriesCore(null, transaction, path, recursive, false, PathFormat.RelativePath); | |||
} | |||
/// <summary>[AlphaFS] Deletes empty subdirectories from the specified directory.</summary> | |||
/// <exception cref="ArgumentException"/> | |||
/// <exception cref="ArgumentNullException"/> | |||
/// <exception cref="ArgumentNullException"/> | |||
/// <exception cref="DirectoryNotFoundException"/> | |||
/// <exception cref="IOException"/> | |||
/// <exception cref="NotSupportedException"/> | |||
/// <exception cref="UnauthorizedAccessException"/> | |||
/// <exception cref="DirectoryReadOnlyException"/> | |||
/// <param name="transaction">The transaction.</param> | |||
/// <param name="path">The name of the directory to remove empty subdirectories from.</param> | |||
/// <param name="recursive"><see langword="true"/> deletes empty subdirectories from this directory and its subdirectories.</param> | |||
@@ -109,15 +164,17 @@ namespace Alphaleonis.Win32.Filesystem | |||
[SecurityCritical] | |||
public static void DeleteEmptySubdirectoriesTransacted(KernelTransaction transaction, string path, bool recursive, PathFormat pathFormat) | |||
{ | |||
DeleteEmptySubdirectoriesCore(null, transaction, path, recursive, false, true, pathFormat); | |||
DeleteEmptySubdirectoriesCore(null, transaction, path, recursive, false, pathFormat); | |||
} | |||
/// <summary>[AlphaFS] Deletes empty subdirectories from the specified directory.</summary> | |||
/// <exception cref="ArgumentException"/> | |||
/// <exception cref="ArgumentNullException"/> | |||
/// <exception cref="ArgumentNullException"/> | |||
/// <exception cref="DirectoryNotFoundException"/> | |||
/// <exception cref="IOException"/> | |||
/// <exception cref="NotSupportedException"/> | |||
/// <exception cref="UnauthorizedAccessException"/> | |||
/// <exception cref="DirectoryReadOnlyException"/> | |||
/// <param name="transaction">The transaction.</param> | |||
/// <param name="path">The name of the directory to remove empty subdirectories from.</param> | |||
/// <param name="recursive"><see langword="true"/> deletes empty subdirectories from this directory and its subdirectories.</param> | |||
@@ -125,13 +182,17 @@ namespace Alphaleonis.Win32.Filesystem | |||
[SecurityCritical] | |||
public static void DeleteEmptySubdirectoriesTransacted(KernelTransaction transaction, string path, bool recursive, bool ignoreReadOnly) | |||
{ | |||
DeleteEmptySubdirectoriesCore(null, transaction, path, recursive, ignoreReadOnly, true, PathFormat.RelativePath); | |||
DeleteEmptySubdirectoriesCore(null, transaction, path, recursive, ignoreReadOnly, PathFormat.RelativePath); | |||
} | |||
/// <summary>[AlphaFS] Deletes empty subdirectories from the specified directory.</summary> | |||
/// <exception cref="ArgumentException"/> | |||
/// <exception cref="ArgumentNullException"/> | |||
/// <exception cref="ArgumentNullException"/> | |||
/// <exception cref="DirectoryNotFoundException"/> | |||
/// <exception cref="IOException"/> | |||
/// <exception cref="NotSupportedException"/> | |||
/// <exception cref="UnauthorizedAccessException"/> | |||
/// <exception cref="DirectoryReadOnlyException"/> | |||
/// <param name="transaction">The transaction.</param> | |||
/// <param name="path">The name of the directory to remove empty subdirectories from.</param> | |||
/// <param name="recursive"><see langword="true"/> deletes empty subdirectories from this directory and its subdirectories.</param> | |||
@@ -140,69 +201,130 @@ namespace Alphaleonis.Win32.Filesystem | |||
[SecurityCritical] | |||
public static void DeleteEmptySubdirectoriesTransacted(KernelTransaction transaction, string path, bool recursive, bool ignoreReadOnly, PathFormat pathFormat) | |||
{ | |||
DeleteEmptySubdirectoriesCore(null, transaction, path, recursive, ignoreReadOnly, true, pathFormat); | |||
DeleteEmptySubdirectoriesCore(null, transaction, path, recursive, ignoreReadOnly, pathFormat); | |||
} | |||
#endregion // Transactional | |||
#region Internal Methods | |||
/// <summary>Delete empty subdirectories from the specified directory.</summary> | |||
/// <summary>[AlphaFS] Delete empty subdirectories from the specified directory.</summary> | |||
/// <exception cref="ArgumentException"/> | |||
/// <exception cref="ArgumentNullException"/> | |||
/// <exception cref="DirectoryNotFoundException"/> | |||
/// <exception cref="IOException"/> | |||
/// <exception cref="NotSupportedException"/> | |||
/// <exception cref="UnauthorizedAccessException"/> | |||
/// <param name="fileSystemEntryInfo">A FileSystemEntryInfo instance. Use either <paramref name="fileSystemEntryInfo"/> or <paramref name="path"/>, not both.</param> | |||
/// <exception cref="DirectoryReadOnlyException"/> | |||
/// <param name="fsEntryInfo">A FileSystemEntryInfo instance. Use either <paramref name="fsEntryInfo"/> or <paramref name="path"/>, not both.</param> | |||
/// <param name="transaction">The transaction.</param> | |||
/// <param name="path">The name of the directory to remove empty subdirectories from. Use either <paramref name="path"/> or <paramref name="fileSystemEntryInfo"/>, not both.</param> | |||
/// <param name="path">The name of the directory to remove empty subdirectories from. Use either <paramref name="path"/> or <paramref name="fsEntryInfo"/>, not both.</param> | |||
/// <param name="recursive"><see langword="true"/> deletes empty subdirectories from this directory and its subdirectories.</param> | |||
/// <param name="ignoreReadOnly"><see langword="true"/> overrides read only <see cref="FileAttributes"/> of empty directories.</param> | |||
/// <param name="initialize">When <see langword="true"/> indicates the method is called externally.</param> | |||
/// <param name="pathFormat">Indicates the format of the path parameter(s).</param> | |||
[SecurityCritical] | |||
internal static void DeleteEmptySubdirectoriesCore(FileSystemEntryInfo fileSystemEntryInfo, KernelTransaction transaction, string path, bool recursive, bool ignoreReadOnly, bool initialize, PathFormat pathFormat) | |||
internal static void DeleteEmptySubdirectoriesCore0(FileSystemEntryInfo fsEntryInfo, KernelTransaction transaction, string path, bool recursive, bool ignoreReadOnly, bool initialize, PathFormat pathFormat) | |||
{ | |||
#region Setup | |||
if (pathFormat == PathFormat.RelativePath) | |||
Path.CheckSupportedPathFormat(path, true, true); | |||
if (fileSystemEntryInfo == null) | |||
if (fsEntryInfo == null) | |||
{ | |||
if (pathFormat == PathFormat.RelativePath) | |||
Path.CheckSupportedPathFormat(path, true, true); | |||
if (!File.ExistsCore(true, transaction, path, pathFormat)) | |||
NativeError.ThrowException(Win32Errors.ERROR_PATH_NOT_FOUND, path); | |||
fileSystemEntryInfo = File.GetFileSystemEntryInfoCore(true, transaction, Path.GetExtendedLengthPathCore(transaction, path, pathFormat, GetFullPathOptions.TrimEnd | GetFullPathOptions.RemoveTrailingDirectorySeparator | GetFullPathOptions.FullCheck) , false, pathFormat); | |||
} | |||
if (fileSystemEntryInfo == null) | |||
throw new ArgumentNullException("path"); | |||
string pathLp = fileSystemEntryInfo.LongFullPath; | |||
fsEntryInfo = File.GetFileSystemEntryInfoCore(true, transaction, Path.GetExtendedLengthPathCore(transaction, path, pathFormat, GetFullPathOptions.TrimEnd | GetFullPathOptions.RemoveTrailingDirectorySeparator | GetFullPathOptions.FullCheck) , false, pathFormat); | |||
if (fsEntryInfo == null) | |||
return; | |||
} | |||
#endregion // Setup | |||
// Ensure path is a directory. | |||
if (!fileSystemEntryInfo.IsDirectory) | |||
throw new IOException(string.Format(CultureInfo.CurrentCulture, Resources.Target_Directory_Is_A_File, pathLp)); | |||
if (!fsEntryInfo.IsDirectory) | |||
throw new IOException(string.Format(CultureInfo.CurrentCulture, Resources.Target_Directory_Is_A_File, fsEntryInfo.LongFullPath)); | |||
var dirEnumOptions = DirectoryEnumerationOptions.Folders; | |||
var dirEnumOptions = DirectoryEnumerationOptions.Folders | DirectoryEnumerationOptions.SkipReparsePoints; | |||
if (recursive) | |||
dirEnumOptions |= DirectoryEnumerationOptions.Recursive; | |||
foreach (var fsei in EnumerateFileSystemEntryInfosCore<FileSystemEntryInfo>(transaction, pathLp, Path.WildcardStarMatchAll, dirEnumOptions, PathFormat.LongFullPath)) | |||
DeleteEmptySubdirectoriesCore(fsei, transaction, null, recursive, ignoreReadOnly, false, PathFormat.LongFullPath); | |||
foreach (var fsei in EnumerateFileSystemEntryInfosCore<FileSystemEntryInfo>(transaction, fsEntryInfo.LongFullPath, Path.WildcardStarMatchAll, dirEnumOptions, PathFormat.LongFullPath)) | |||
DeleteEmptySubdirectoriesCore0(fsei, transaction, null, recursive, ignoreReadOnly, false, PathFormat.LongFullPath); | |||
if (!EnumerateFileSystemEntryInfosCore<string>(transaction, pathLp, Path.WildcardStarMatchAll, DirectoryEnumerationOptions.FilesAndFolders, PathFormat.LongFullPath).Any()) | |||
if (!EnumerateFileSystemEntryInfosCore<string>(transaction, fsEntryInfo.LongFullPath, Path.WildcardStarMatchAll, DirectoryEnumerationOptions.FilesAndFolders, PathFormat.LongFullPath).Any()) | |||
{ | |||
// Prevent deleting path itself. | |||
if (!initialize) | |||
DeleteDirectoryCore(fileSystemEntryInfo, transaction, null, false, ignoreReadOnly, true, true, PathFormat.LongFullPath); | |||
DeleteDirectoryCore(fsEntryInfo, transaction, null, false, ignoreReadOnly, true, PathFormat.LongFullPath); | |||
} | |||
} | |||
/// <summary>[AlphaFS] Delete empty subdirectories from the specified directory.</summary> | |||
/// <exception cref="ArgumentException"/> | |||
/// <exception cref="ArgumentNullException"/> | |||
/// <exception cref="DirectoryNotFoundException"/> | |||
/// <exception cref="IOException"/> | |||
/// <exception cref="NotSupportedException"/> | |||
/// <exception cref="UnauthorizedAccessException"/> | |||
/// <exception cref="DirectoryReadOnlyException"/> | |||
/// <param name="fsEntryInfo">A FileSystemEntryInfo instance. Use either <paramref name="fsEntryInfo"/> or <paramref name="path"/>, not both.</param> | |||
/// <param name="transaction">The transaction.</param> | |||
/// <param name="path">The name of the directory to remove empty subdirectories from. Use either <paramref name="path"/> or <paramref name="fsEntryInfo"/>, not both.</param> | |||
/// <param name="recursive"><see langword="true"/> deletes empty subdirectories from this directory and its subdirectories.</param> | |||
/// <param name="ignoreReadOnly"><see langword="true"/> overrides read only <see cref="FileAttributes"/> of empty directories.</param> | |||
/// <param name="pathFormat">Indicates the format of the path parameter(s).</param> | |||
[SecurityCritical] | |||
internal static void DeleteEmptySubdirectoriesCore(FileSystemEntryInfo fsEntryInfo, KernelTransaction transaction, string path, bool recursive, bool ignoreReadOnly, PathFormat pathFormat) | |||
{ | |||
#region Setup | |||
if (fsEntryInfo == null) | |||
{ | |||
if (pathFormat == PathFormat.RelativePath) | |||
Path.CheckSupportedPathFormat(path, true, true); | |||
if (!File.ExistsCore(true, transaction, path, pathFormat)) | |||
NativeError.ThrowException(Win32Errors.ERROR_PATH_NOT_FOUND, path); | |||
fsEntryInfo = File.GetFileSystemEntryInfoCore(true, transaction, Path.GetExtendedLengthPathCore(transaction, path, pathFormat, GetFullPathOptions.TrimEnd | GetFullPathOptions.RemoveTrailingDirectorySeparator | GetFullPathOptions.FullCheck), false, pathFormat); | |||
if (fsEntryInfo == null) | |||
return; | |||
} | |||
#endregion // Setup | |||
// Ensure path is a directory. | |||
if (!fsEntryInfo.IsDirectory) | |||
throw new IOException(string.Format(CultureInfo.CurrentCulture, Resources.Target_Directory_Is_A_File, fsEntryInfo.LongFullPath)); | |||
var dirs = new Stack<string>(1000); | |||
dirs.Push(fsEntryInfo.LongFullPath); | |||
while (dirs.Count > 0) | |||
{ | |||
foreach (var fsei in EnumerateFileSystemEntryInfosCore<FileSystemEntryInfo>(transaction, dirs.Pop(), Path.WildcardStarMatchAll, DirectoryEnumerationOptions.Folders | DirectoryEnumerationOptions.ContinueOnException, PathFormat.LongFullPath)) | |||
{ | |||
// Ensure the directory is empty. | |||
if (!EnumerateFileSystemEntryInfosCore<string>(transaction, fsei.LongFullPath, Path.WildcardStarMatchAll, DirectoryEnumerationOptions.FilesAndFolders, PathFormat.LongFullPath).Any()) | |||
DeleteDirectoryCore(fsei, transaction, null, false, ignoreReadOnly, true, PathFormat.LongFullPath); | |||
else if (recursive) | |||
dirs.Push(fsei.LongFullPath); | |||
} | |||
} | |||
} | |||
@@ -20,6 +20,7 @@ | |||
*/ | |||
using System; | |||
using System.Diagnostics.CodeAnalysis; | |||
using System.Security; | |||
using System.Security.AccessControl; | |||
@@ -54,6 +55,7 @@ namespace Alphaleonis.Win32.Filesystem | |||
/// If the subdirectory already exists, this method does nothing. | |||
/// </remarks> | |||
[SuppressMessage("Microsoft.Design", "CA1011:ConsiderPassingBaseTypesAsParameters")] | |||
[SecurityCritical] | |||
public DirectoryInfo CreateSubdirectory(string path, DirectorySecurity directorySecurity) | |||
{ | |||
@@ -108,6 +110,7 @@ namespace Alphaleonis.Win32.Filesystem | |||
/// If the subdirectory already exists, this method does nothing. | |||
/// </remarks> | |||
[SuppressMessage("Microsoft.Design", "CA1011:ConsiderPassingBaseTypesAsParameters")] | |||
[SecurityCritical] | |||
public DirectoryInfo CreateSubdirectory(string path, DirectorySecurity directorySecurity, bool compress) | |||
{ | |||
@@ -126,6 +129,7 @@ namespace Alphaleonis.Win32.Filesystem | |||
/// If the subdirectory already exists, this method does nothing. | |||
/// </remarks> | |||
[SuppressMessage("Microsoft.Design", "CA1011:ConsiderPassingBaseTypesAsParameters")] | |||
[SecurityCritical] | |||
public DirectoryInfo CreateSubdirectory(string path, string templatePath, DirectorySecurity directorySecurity, bool compress) | |||
{ | |||
@@ -148,7 +152,7 @@ namespace Alphaleonis.Win32.Filesystem | |||
/// <param name="directorySecurity">The <see cref="DirectorySecurity"/> security to apply.</param> | |||
/// <param name="compress">When <see langword="true"/> compresses the directory.</param> | |||
[SecurityCritical] | |||
private DirectoryInfo CreateSubdirectoryCore(string path, string templatePath, DirectorySecurity directorySecurity, bool compress) | |||
private DirectoryInfo CreateSubdirectoryCore(string path, string templatePath, ObjectSecurity directorySecurity, bool compress) | |||
{ | |||
string pathLp = Path.CombineCore(false, LongFullName, path); | |||
string templatePathLp = templatePath == null ? null : | |||
@@ -39,7 +39,7 @@ namespace Alphaleonis.Win32.Filesystem | |||
[SecurityCritical] | |||
public override void Delete() | |||
{ | |||
Directory.DeleteDirectoryCore(null, Transaction, LongFullName, false, false, true, false, PathFormat.LongFullPath); | |||
Directory.DeleteDirectoryCore(EntryInfo, Transaction, null, false, false, false, PathFormat.LongFullPath); | |||
} | |||
/// <summary>Deletes this instance of a <see cref="DirectoryInfo"/>, specifying whether to delete subdirectories and files.</summary> | |||
@@ -57,7 +57,7 @@ namespace Alphaleonis.Win32.Filesystem | |||
[SecurityCritical] | |||
public void Delete(bool recursive) | |||
{ | |||
Directory.DeleteDirectoryCore(null, Transaction, LongFullName, recursive, false, !recursive, false, PathFormat.LongFullPath); | |||
Directory.DeleteDirectoryCore(EntryInfo, Transaction, null, recursive, false, false, PathFormat.LongFullPath); | |||
} | |||
#endregion // .NET | |||
@@ -80,7 +80,7 @@ namespace Alphaleonis.Win32.Filesystem | |||
[SecurityCritical] | |||
public void Delete(bool recursive, bool ignoreReadOnly) | |||
{ | |||
Directory.DeleteDirectoryCore(null, Transaction, LongFullName, recursive, ignoreReadOnly, !recursive, false, PathFormat.LongFullPath); | |||
Directory.DeleteDirectoryCore(EntryInfo, Transaction, null, recursive, ignoreReadOnly, false, PathFormat.LongFullPath); | |||
} | |||
#endregion // AlphaFS | |||
@@ -32,7 +32,7 @@ namespace Alphaleonis.Win32.Filesystem | |||
[SecurityCritical] | |||
public void DeleteEmptySubdirectories() | |||
{ | |||
Directory.DeleteEmptySubdirectoriesCore(null, Transaction, LongFullName, false, false, true, PathFormat.LongFullPath); | |||
Directory.DeleteEmptySubdirectoriesCore(EntryInfo, Transaction, null, false, false, PathFormat.LongFullPath); | |||
} | |||
/// <summary>[AlphaFS] Deletes empty subdirectories from the <see cref="DirectoryInfo"/> instance.</summary> | |||
@@ -40,7 +40,7 @@ namespace Alphaleonis.Win32.Filesystem | |||
[SecurityCritical] | |||
public void DeleteEmptySubdirectories(bool recursive) | |||
{ | |||
Directory.DeleteEmptySubdirectoriesCore(null, Transaction, LongFullName, recursive, false, true, PathFormat.LongFullPath); | |||
Directory.DeleteEmptySubdirectoriesCore(EntryInfo, Transaction, null, recursive, false, PathFormat.LongFullPath); | |||
} | |||
/// <summary>[AlphaFS] Deletes empty subdirectories from the <see cref="DirectoryInfo"/> instance.</summary> | |||
@@ -49,7 +49,7 @@ namespace Alphaleonis.Win32.Filesystem | |||
[SecurityCritical] | |||
public void DeleteEmptySubdirectories(bool recursive, bool ignoreReadOnly) | |||
{ | |||
Directory.DeleteEmptySubdirectoriesCore(null, Transaction, LongFullName, recursive, ignoreReadOnly, true, PathFormat.LongFullPath); | |||
Directory.DeleteEmptySubdirectoriesCore(EntryInfo, Transaction, null, recursive, ignoreReadOnly, PathFormat.LongFullPath); | |||
} | |||
#endregion // AlphaFS | |||
@@ -25,22 +25,22 @@ namespace Alphaleonis.Win32.Filesystem | |||
public enum CopyMoveProgressResult | |||
{ | |||
/// <summary>PROGRESS_CONTINUE | |||
/// <para>Continue the copy operation.</para> | |||
/// <para>Continue the copy/move operation.</para> | |||
/// </summary> | |||
Continue = 0, | |||
/// <summary>PROGRESS_CANCEL | |||
/// <para>Cancel the copy operation and delete the destination file.</para> | |||
/// <para>Cancel the copy/move operation and delete the destination file.</para> | |||
/// </summary> | |||
Cancel = 1, | |||
/// <summary>PROGRESS_STOP | |||
/// <para>Stop the copy operation. It can be restarted at a later time.</para> | |||
/// <para>Stop the copy/move operation. It can be restarted at a later time.</para> | |||
/// </summary> | |||
Stop = 2, | |||
/// <summary>PROGRESS_QUIET | |||
/// <para>Continue the copy operation, but stop invoking <see cref="CopyMoveProgressRoutine"/> to report progress.</para> | |||
/// <para>Continue the copy/move operation, but stop invoking <see cref="CopyMoveProgressRoutine"/> to report progress.</para> | |||
/// </summary> | |||
Quiet = 3 | |||
} |
@@ -55,7 +55,7 @@ namespace Alphaleonis.Win32.Filesystem | |||
/// This flag must be set in the Flags parameter if the Enumerator parameter specifies a Device Instance ID. | |||
/// </para> | |||
/// </summary> | |||
DeviceInterface = 16, | |||
DeviceInterface = 16 | |||
} | |||
} | |||
} |
@@ -55,6 +55,6 @@ namespace Alphaleonis.Win32.Filesystem | |||
/// <para>Do not broadcast the WM_SETTINGCHANGE message.</para> | |||
/// <para>By default, this message is broadcast to notify the shell and applications of the change.</para> | |||
/// </summary> | |||
NoBroadcastSystem = 8, | |||
NoBroadcastSystem = 8 | |||
} | |||
} |
@@ -26,7 +26,7 @@ using System.IO; | |||
namespace Alphaleonis.Win32.Filesystem | |||
{ | |||
/// <summary>Specifies how the operating system should open a file.</summary> | |||
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2217:DoNotMarkEnumsWithFlags")] | |||
[SuppressMessage("Microsoft.Usage", "CA2217:DoNotMarkEnumsWithFlags")] | |||
[Flags] | |||
public enum ExtendedFileAttributes | |||
{ | |||
@@ -138,7 +138,7 @@ namespace Alphaleonis.Win32.Filesystem | |||
/// <para>will resume the enumeration operation after the last file is returned.</para> | |||
/// </remarks> | |||
/// </summary> | |||
FileIdBothDirectoryInfo = 10, | |||
FileIdBothDirectoryInfo = 10 | |||
#endregion // FILE_ID_BOTH_DIR_INFO | |||
@@ -28,6 +28,6 @@ namespace Alphaleonis.Win32.Filesystem | |||
Absolute = 0, | |||
/// <summary>The symbolic link is relative.</summary> | |||
Relative = 1, | |||
Relative = 1 | |||
} | |||
} |
@@ -35,24 +35,21 @@ namespace Alphaleonis.Win32.Filesystem | |||
/// <summary>Initializes a new instance of the <see cref="TransactionException"/> class.</summary> | |||
/// <param name="message">The message.</param> | |||
public TransactionException(string message) | |||
: base(message) | |||
public TransactionException(string message) : base(message) | |||
{ | |||
} | |||
/// <summary>Initializes a new instance of the <see cref="TransactionException"/> class.</summary> | |||
/// <param name="message">The message.</param> | |||
/// <param name="innerException">The inner exception.</param> | |||
public TransactionException(string message, Exception innerException) | |||
: base(message, innerException) | |||
public TransactionException(string message, Exception innerException) : base(message, innerException) | |||
{ | |||
} | |||
/// <summary>Initializes a new instance of the <see cref="TransactionException"/> class.</summary> | |||
/// <param name="info">The data for serializing or deserializing the object.</param> | |||
/// <param name="context">The source and destination for the object.</param> | |||
protected TransactionException(SerializationInfo info, StreamingContext context) | |||
: base(info, context) | |||
protected TransactionException(SerializationInfo info, StreamingContext context) : base(info, context) | |||
{ | |||
} | |||
} |
@@ -359,9 +359,9 @@ namespace Alphaleonis.Win32.Filesystem | |||
/// <param name="progressHandler">A callback function that is called each time another portion of the file has been copied. This parameter can be <see langword="null"/>.</param> | |||
/// <param name="userProgressData">The argument to be passed to the callback function. This parameter can be <see langword="null"/>.</param> | |||
[SecurityCritical] | |||
public static CopyMoveResult Copy(string sourceFileName, string destinationFileName, CopyOptions copyOptions, CopyMoveProgressRoutine progressHandler, object userProgressData) | |||
public static void Copy(string sourceFileName, string destinationFileName, CopyOptions copyOptions, CopyMoveProgressRoutine progressHandler, object userProgressData) | |||
{ | |||
return CopyMoveCore(false, null, sourceFileName, destinationFileName, false, copyOptions, null, progressHandler, userProgressData, null, PathFormat.RelativePath); | |||
CopyMoveCore(false, null, sourceFileName, destinationFileName, false, copyOptions, null, progressHandler, userProgressData, null, PathFormat.RelativePath); | |||
} | |||
/// <summary>[AlphaFS] Copies an existing file to a new file. Overwriting a file of the same name is allowed. <see cref="CopyOptions"/> can be specified, | |||
@@ -388,9 +388,9 @@ namespace Alphaleonis.Win32.Filesystem | |||
/// <param name="userProgressData">The argument to be passed to the callback function. This parameter can be <see langword="null"/>.</param> | |||
/// <param name="pathFormat">Indicates the format of the path parameter(s).</param> | |||
[SecurityCritical] | |||
public static CopyMoveResult Copy(string sourceFileName, string destinationFileName, CopyOptions copyOptions, CopyMoveProgressRoutine progressHandler, object userProgressData, PathFormat pathFormat) | |||
public static void Copy(string sourceFileName, string destinationFileName, CopyOptions copyOptions, CopyMoveProgressRoutine progressHandler, object userProgressData, PathFormat pathFormat) | |||
{ | |||
return CopyMoveCore(false, null, sourceFileName, destinationFileName, false, copyOptions, null, progressHandler, userProgressData, null, pathFormat); | |||
CopyMoveCore(false, null, sourceFileName, destinationFileName, false, copyOptions, null, progressHandler, userProgressData, null, pathFormat); | |||
} | |||
@@ -418,9 +418,9 @@ namespace Alphaleonis.Win32.Filesystem | |||
/// <param name="progressHandler">A callback function that is called each time another portion of the file has been copied. This parameter can be <see langword="null"/>.</param> | |||
/// <param name="userProgressData">The argument to be passed to the callback function. This parameter can be <see langword="null"/>.</param> | |||
[SecurityCritical] | |||
public static CopyMoveResult Copy(string sourceFileName, string destinationFileName, CopyOptions copyOptions, bool preserveDates, CopyMoveProgressRoutine progressHandler, object userProgressData) | |||
public static void Copy(string sourceFileName, string destinationFileName, CopyOptions copyOptions, bool preserveDates, CopyMoveProgressRoutine progressHandler, object userProgressData) | |||
{ | |||
return CopyMoveCore(false, null, sourceFileName, destinationFileName, preserveDates, copyOptions, null, progressHandler, userProgressData, null, PathFormat.RelativePath); | |||
CopyMoveCore(false, null, sourceFileName, destinationFileName, preserveDates, copyOptions, null, progressHandler, userProgressData, null, PathFormat.RelativePath); | |||
} | |||
/// <summary>[AlphaFS] Copies an existing file to a new file. Overwriting a file of the same name is allowed. <see cref="CopyOptions"/> can be specified, | |||
@@ -448,9 +448,9 @@ namespace Alphaleonis.Win32.Filesystem | |||
/// <param name="userProgressData">The argument to be passed to the callback function. This parameter can be <see langword="null"/>.</param> | |||
/// <param name="pathFormat">Indicates the format of the path parameter(s).</param> | |||
[SecurityCritical] | |||
public static CopyMoveResult Copy(string sourceFileName, string destinationFileName, CopyOptions copyOptions, bool preserveDates, CopyMoveProgressRoutine progressHandler, object userProgressData, PathFormat pathFormat) | |||
public static void Copy(string sourceFileName, string destinationFileName, CopyOptions copyOptions, bool preserveDates, CopyMoveProgressRoutine progressHandler, object userProgressData, PathFormat pathFormat) | |||
{ | |||
return CopyMoveCore(false, null, sourceFileName, destinationFileName, preserveDates, copyOptions, null, progressHandler, userProgressData, null, pathFormat); | |||
CopyMoveCore(false, null, sourceFileName, destinationFileName, preserveDates, copyOptions, null, progressHandler, userProgressData, null, pathFormat); | |||
} | |||
#endregion // Non-Transactional | |||
@@ -584,9 +584,9 @@ namespace Alphaleonis.Win32.Filesystem | |||
/// <param name="progressHandler">A callback function that is called each time another portion of the file has been copied. This parameter can be <see langword="null"/>.</param> | |||
/// <param name="userProgressData">The argument to be passed to the callback function. This parameter can be <see langword="null"/>.</param> | |||
[SecurityCritical] | |||
public static CopyMoveResult CopyTransacted(KernelTransaction transaction, string sourceFileName, string destinationFileName, CopyOptions copyOptions, CopyMoveProgressRoutine progressHandler, object userProgressData) | |||
public static void CopyTransacted(KernelTransaction transaction, string sourceFileName, string destinationFileName, CopyOptions copyOptions, CopyMoveProgressRoutine progressHandler, object userProgressData) | |||
{ | |||
return CopyMoveCore(false, transaction, sourceFileName, destinationFileName, false, copyOptions, null, progressHandler, userProgressData, null, PathFormat.RelativePath); | |||
CopyMoveCore(false, transaction, sourceFileName, destinationFileName, false, copyOptions, null, progressHandler, userProgressData, null, PathFormat.RelativePath); | |||
} | |||
/// <summary>[AlphaFS] Copies an existing file to a new file. Overwriting a file of the same name is allowed. <see cref="CopyOptions"/> can be specified, | |||
@@ -614,9 +614,9 @@ namespace Alphaleonis.Win32.Filesystem | |||
/// <param name="userProgressData">The argument to be passed to the callback function. This parameter can be <see langword="null"/>.</param> | |||
/// <param name="pathFormat">Indicates the format of the path parameter(s).</param> | |||
[SecurityCritical] | |||
public static CopyMoveResult CopyTransacted(KernelTransaction transaction, string sourceFileName, string destinationFileName, CopyOptions copyOptions, CopyMoveProgressRoutine progressHandler, object userProgressData, PathFormat pathFormat) | |||
public static void CopyTransacted(KernelTransaction transaction, string sourceFileName, string destinationFileName, CopyOptions copyOptions, CopyMoveProgressRoutine progressHandler, object userProgressData, PathFormat pathFormat) | |||
{ | |||
return CopyMoveCore(false, transaction, sourceFileName, destinationFileName, false, copyOptions, null, progressHandler, userProgressData, null, pathFormat); | |||
CopyMoveCore(false, transaction, sourceFileName, destinationFileName, false, copyOptions, null, progressHandler, userProgressData, null, pathFormat); | |||
} | |||
@@ -645,9 +645,9 @@ namespace Alphaleonis.Win32.Filesystem | |||
/// <param name="progressHandler">A callback function that is called each time another portion of the file has been copied. This parameter can be <see langword="null"/>.</param> | |||
/// <param name="userProgressData">The argument to be passed to the callback function. This parameter can be <see langword="null"/>.</param> | |||
[SecurityCritical] | |||
public static CopyMoveResult CopyTransacted(KernelTransaction transaction, string sourceFileName, string destinationFileName, CopyOptions copyOptions, bool preserveDates, CopyMoveProgressRoutine progressHandler, object userProgressData) | |||
public static void CopyTransacted(KernelTransaction transaction, string sourceFileName, string destinationFileName, CopyOptions copyOptions, bool preserveDates, CopyMoveProgressRoutine progressHandler, object userProgressData) | |||
{ | |||
return CopyMoveCore(false, transaction, sourceFileName, destinationFileName, preserveDates, copyOptions, null, progressHandler, userProgressData, null, PathFormat.RelativePath); | |||
CopyMoveCore(false, transaction, sourceFileName, destinationFileName, preserveDates, copyOptions, null, progressHandler, userProgressData, null, PathFormat.RelativePath); | |||
} | |||
/// <summary>[AlphaFS] Copies an existing file to a new file. Overwriting a file of the same name is allowed. <see cref="CopyOptions"/> can be specified, | |||
@@ -676,9 +676,9 @@ namespace Alphaleonis.Win32.Filesystem | |||
/// <exception cref="NotSupportedException"/> | |||
/// <exception cref="UnauthorizedAccessException"/> | |||
[SecurityCritical] | |||
public static CopyMoveResult CopyTransacted(KernelTransaction transaction, string sourceFileName, string destinationFileName, CopyOptions copyOptions, bool preserveDates, CopyMoveProgressRoutine progressHandler, object userProgressData, PathFormat pathFormat) | |||
public static void CopyTransacted(KernelTransaction transaction, string sourceFileName, string destinationFileName, CopyOptions copyOptions, bool preserveDates, CopyMoveProgressRoutine progressHandler, object userProgressData, PathFormat pathFormat) | |||
{ | |||
return CopyMoveCore(false, transaction, sourceFileName, destinationFileName, preserveDates, copyOptions, null, progressHandler, userProgressData, null, pathFormat); | |||
CopyMoveCore(false, transaction, sourceFileName, destinationFileName, preserveDates, copyOptions, null, progressHandler, userProgressData, null, pathFormat); | |||
} | |||
#endregion // Transactional | |||
@@ -880,9 +880,9 @@ namespace Alphaleonis.Win32.Filesystem | |||
/// <param name="progressHandler">A callback function that is called each time another portion of the file has been moved. This parameter can be <see langword="null"/>.</param> | |||
/// <param name="userProgressData">The argument to be passed to the callback function. This parameter can be <see langword="null"/>.</param> | |||
[SecurityCritical] | |||
public static CopyMoveResult Move(string sourceFileName, string destinationFileName, MoveOptions moveOptions, CopyMoveProgressRoutine progressHandler, object userProgressData) | |||
public static void Move(string sourceFileName, string destinationFileName, MoveOptions moveOptions, CopyMoveProgressRoutine progressHandler, object userProgressData) | |||
{ | |||
return CopyMoveCore(false, null, sourceFileName, destinationFileName, false, null, moveOptions, progressHandler, userProgressData, null, PathFormat.RelativePath); | |||
CopyMoveCore(false, null, sourceFileName, destinationFileName, false, null, moveOptions, progressHandler, userProgressData, null, PathFormat.RelativePath); | |||
} | |||
/// <summary>[AlphaFS] Moves a specified file to a new location, providing the option to specify a new file name.</summary> | |||
@@ -908,9 +908,9 @@ namespace Alphaleonis.Win32.Filesystem | |||
/// <param name="userProgressData">The argument to be passed to the callback function. This parameter can be <see langword="null"/>.</param> | |||
/// <param name="pathFormat">Indicates the format of the path parameter(s).</param> | |||
[SecurityCritical] | |||
public static CopyMoveResult Move(string sourceFileName, string destinationFileName, MoveOptions moveOptions, CopyMoveProgressRoutine progressHandler, object userProgressData, PathFormat pathFormat) | |||
public static void Move(string sourceFileName, string destinationFileName, MoveOptions moveOptions, CopyMoveProgressRoutine progressHandler, object userProgressData, PathFormat pathFormat) | |||
{ | |||
return CopyMoveCore(false, null, sourceFileName, destinationFileName, false, null, moveOptions, progressHandler, userProgressData, null, pathFormat); | |||
CopyMoveCore(false, null, sourceFileName, destinationFileName, false, null, moveOptions, progressHandler, userProgressData, null, pathFormat); | |||
} | |||
#endregion // Non-Transactional | |||
@@ -993,9 +993,9 @@ namespace Alphaleonis.Win32.Filesystem | |||
/// <param name="progressHandler">A callback function that is called each time another portion of the file has been moved. This parameter can be <see langword="null"/>.</param> | |||
/// <param name="userProgressData">The argument to be passed to the callback function. This parameter can be <see langword="null"/>.</param> | |||
[SecurityCritical] | |||
public static CopyMoveResult MoveTransacted(KernelTransaction transaction, string sourceFileName, string destinationFileName, MoveOptions moveOptions, CopyMoveProgressRoutine progressHandler, object userProgressData) | |||
public static void MoveTransacted(KernelTransaction transaction, string sourceFileName, string destinationFileName, MoveOptions moveOptions, CopyMoveProgressRoutine progressHandler, object userProgressData) | |||
{ | |||
return CopyMoveCore(false, transaction, sourceFileName, destinationFileName, false, null, moveOptions, progressHandler, userProgressData, null, PathFormat.RelativePath); | |||
CopyMoveCore(false, transaction, sourceFileName, destinationFileName, false, null, moveOptions, progressHandler, userProgressData, null, PathFormat.RelativePath); | |||
} | |||
/// <summary>[AlphaFS] Moves a specified file to a new location, providing the option to specify a new file name.</summary> | |||
@@ -1022,9 +1022,9 @@ namespace Alphaleonis.Win32.Filesystem | |||
/// <param name="userProgressData">The argument to be passed to the callback function. This parameter can be <see langword="null"/>.</param> | |||
/// <param name="pathFormat">Indicates the format of the path parameter(s).</param> | |||
[SecurityCritical] | |||
public static CopyMoveResult MoveTransacted(KernelTransaction transaction, string sourceFileName, string destinationFileName, MoveOptions moveOptions, CopyMoveProgressRoutine progressHandler, object userProgressData, PathFormat pathFormat) | |||
public static void MoveTransacted(KernelTransaction transaction, string sourceFileName, string destinationFileName, MoveOptions moveOptions, CopyMoveProgressRoutine progressHandler, object userProgressData, PathFormat pathFormat) | |||
{ | |||
return CopyMoveCore(false, transaction, sourceFileName, destinationFileName, false, null, moveOptions, progressHandler, userProgressData, null, pathFormat); | |||
CopyMoveCore(false, transaction, sourceFileName, destinationFileName, false, null, moveOptions, progressHandler, userProgressData, null, pathFormat); | |||
} | |||
#endregion // Transactional | |||
@@ -1087,10 +1087,8 @@ namespace Alphaleonis.Win32.Filesystem | |||
var sourceFileNameLp = sourceFileName; | |||
var destFileNameLp = destinationFileName; | |||
var skipPathChecks = pathFormat == PathFormat.LongFullPath; | |||
if (!skipPathChecks) | |||
if (pathFormat != PathFormat.LongFullPath) | |||
{ | |||
Path.CheckSupportedPathFormat(sourceFileName, true, true); | |||
Path.CheckSupportedPathFormat(destinationFileName, true, true); | |||
@@ -1098,30 +1096,27 @@ namespace Alphaleonis.Win32.Filesystem | |||
sourceFileNameLp = Path.GetExtendedLengthPathCore(transaction, sourceFileName, pathFormat, GetFullPathOptions.RemoveTrailingDirectorySeparator); | |||
destFileNameLp = Path.GetExtendedLengthPathCore(transaction, destinationFileName, pathFormat, GetFullPathOptions.RemoveTrailingDirectorySeparator); | |||
} | |||
// MSDN: If this flag is set to TRUE during the copy/move operation, the operation is canceled. | |||
// Otherwise, the copy/move operation will continue to completion. | |||
var cancel = false; | |||
// Determine Copy or Move action. | |||
var isCopy = DetermineIsCopy(copyOptions, moveOptions); | |||
var isMove = !isCopy; | |||
var cmr = copyMoveResult ?? new CopyMoveResult(sourceFileName, destinationFileName, false, (int) Win32Errors.ERROR_SUCCESS); | |||
var raiseException = progressHandler == null; | |||
//Task completedTask = null; | |||
// MSDN: If this flag is set to TRUE during the copy/move operation, the operation is canceled. | |||
// Otherwise, the copy/move operation will continue to completion. | |||
bool cancel; | |||
var raiseException = progressHandler == null; | |||
// Setup callback function for progress notifications. | |||
var routine = progressHandler != null | |||
var routine = !raiseException | |||
? (totalFileSize, totalBytesTransferred, streamSize, streamBytesTransferred, dwStreamNumber, dwCallbackReason, hSourceFile, hDestinationFile, lpData) => | |||
progressHandler(totalFileSize, totalBytesTransferred, streamSize, streamBytesTransferred, dwStreamNumber, dwCallbackReason, userProgressData) | |||
: (NativeMethods.NativeCopyMoveProgressRoutine) null; | |||
var cmr = copyMoveResult ?? new CopyMoveResult(sourceFileNameLp, destFileNameLp, false, (int) Win32Errors.ERROR_SUCCESS); | |||
#endregion // Setup | |||
@@ -1153,8 +1148,6 @@ namespace Alphaleonis.Win32.Filesystem | |||
: isMove | |||
? NativeMethods.MoveFileTransacted(sourceFileNameLp, destFileNameLp, routine, IntPtr.Zero, (MoveOptions) moveOptions, transaction.SafeHandle) | |||
: NativeMethods.CopyFileTransacted(sourceFileNameLp, destFileNameLp, routine, IntPtr.Zero, out cancel, (CopyOptions) copyOptions, transaction.SafeHandle); | |||
var lastError = (uint) Marshal.GetLastWin32Error(); | |||
@@ -1174,8 +1167,7 @@ namespace Alphaleonis.Win32.Filesystem | |||
// CopyFileEx will return zero and GetLastError will return ERROR_REQUEST_ABORTED. | |||
// In this case, the partially copied destination file is left intact. | |||
cancel = true; | |||
cmr.IsCanceled = cancel; | |||
cmr.IsCanceled = true; | |||
} | |||
else if (raiseException) | |||
@@ -1267,7 +1259,7 @@ namespace Alphaleonis.Win32.Filesystem | |||
if (((MoveOptions) moveOptions & MoveOptions.ReplaceExisting) != 0) | |||
{ | |||
// Reset file system object attributes. | |||
SetAttributesCore(isFolder, transaction, destFileNameLp, FileAttributes.Normal, true, PathFormat.LongFullPath); | |||
SetAttributesCore(isFolder, transaction, destFileNameLp, FileAttributes.Normal, PathFormat.LongFullPath); | |||
goto startCopyMove; | |||
} | |||
@@ -96,7 +96,7 @@ namespace Alphaleonis.Win32.Filesystem | |||
[SecurityCritical] | |||
internal static void CreateHardlinkCore(KernelTransaction transaction, string fileName, string existingFileName, PathFormat pathFormat) | |||
{ | |||
var options = GetFullPathOptions.RemoveTrailingDirectorySeparator | GetFullPathOptions.FullCheck; | |||
const GetFullPathOptions options = GetFullPathOptions.RemoveTrailingDirectorySeparator | GetFullPathOptions.FullCheck; | |||
string fileNameLp = Path.GetExtendedLengthPathCore(transaction, fileName, pathFormat, options); | |||
string existingFileNameLp = Path.GetExtendedLengthPathCore(transaction, existingFileName, pathFormat, options); | |||
@@ -110,7 +110,7 @@ namespace Alphaleonis.Win32.Filesystem | |||
if (!NativeMethods.IsAtLeastWindowsVista) | |||
throw new PlatformNotSupportedException(Resources.Requires_Windows_Vista_Or_Higher); | |||
var options = GetFullPathOptions.RemoveTrailingDirectorySeparator | GetFullPathOptions.FullCheck; | |||
const GetFullPathOptions options = GetFullPathOptions.RemoveTrailingDirectorySeparator | GetFullPathOptions.FullCheck; | |||
string symlinkFileNameLp = Path.GetExtendedLengthPathCore(transaction, symlinkFileName, pathFormat, options); | |||
string targetFileNameRp = Path.GetExtendedLengthPathCore(transaction, targetFileName, pathFormat, options); | |||
@@ -209,7 +209,7 @@ namespace Alphaleonis.Win32.Filesystem | |||
if (ignoreReadOnly) | |||
{ | |||
// Reset file attributes. | |||
SetAttributesCore(false, transaction, pathLp, FileAttributes.Normal, true, PathFormat.LongFullPath); | |||
SetAttributesCore(false, transaction, pathLp, FileAttributes.Normal, PathFormat.LongFullPath); | |||
goto startDeleteFile; | |||
} | |||
@@ -85,7 +85,7 @@ namespace Alphaleonis.Win32.Filesystem | |||
// Reset file/directory attributes. | |||
// MSDN: If lpFileName specifies a read-only file, the function fails and GetLastError returns ERROR_FILE_READ_ONLY. | |||
SetAttributesCore(isFolder, null, pathLp, FileAttributes.Normal, true, PathFormat.LongFullPath); | |||
SetAttributesCore(isFolder, null, pathLp, FileAttributes.Normal, PathFormat.LongFullPath); | |||
// EncryptFile() / DecryptFile() | |||
// In the ANSI version of this function, the name is limited to 248 characters. | |||
@@ -83,7 +83,7 @@ namespace Alphaleonis.Win32.Filesystem | |||
[SecurityCritical] | |||
internal static string GetHashCore(KernelTransaction transaction, string fileFullPath, HashType hashType, PathFormat pathFormat) | |||
{ | |||
var options = GetFullPathOptions.RemoveTrailingDirectorySeparator | GetFullPathOptions.FullCheck; | |||
const GetFullPathOptions options = GetFullPathOptions.RemoveTrailingDirectorySeparator | GetFullPathOptions.FullCheck; | |||
var fileNameLp = Path.GetExtendedLengthPathCore(transaction, fileFullPath, pathFormat, options); | |||
byte[] hash = null; | |||
@@ -151,7 +151,7 @@ namespace Alphaleonis.Win32.Filesystem | |||
[SecurityCritical] | |||
internal static void ReplaceCore(string sourceFileName, string destinationFileName, string destinationBackupFileName, bool ignoreMetadataErrors, PathFormat pathFormat) | |||
{ | |||
var options = GetFullPathOptions.RemoveTrailingDirectorySeparator | GetFullPathOptions.FullCheck; | |||
const GetFullPathOptions options = GetFullPathOptions.RemoveTrailingDirectorySeparator | GetFullPathOptions.FullCheck; | |||
string sourceFileNameLp = Path.GetExtendedLengthPathCore(null, sourceFileName, pathFormat, options); | |||
string destinationFileNameLp = Path.GetExtendedLengthPathCore(null, destinationFileName, pathFormat, options); | |||
@@ -44,7 +44,7 @@ namespace Alphaleonis.Win32.Filesystem | |||
[SecurityCritical] | |||
public static void SetAttributes(string path, FileAttributes fileAttributes) | |||
{ | |||
SetAttributesCore(false, null, path, fileAttributes, false, PathFormat.RelativePath); | |||
SetAttributesCore(false, null, path, fileAttributes, PathFormat.RelativePath); | |||
} | |||
/// <summary>[AlphaFS] Sets the specified <see cref="FileAttributes"/> of the file or directory on the specified path.</summary> | |||
@@ -61,7 +61,7 @@ namespace Alphaleonis.Win32.Filesystem | |||
[SecurityCritical] | |||
public static void SetAttributes(string path, FileAttributes fileAttributes, PathFormat pathFormat) | |||
{ | |||
SetAttributesCore(false, null, path, fileAttributes, false, pathFormat); | |||
SetAttributesCore(false, null, path, fileAttributes, pathFormat); | |||
} | |||
@@ -81,7 +81,7 @@ namespace Alphaleonis.Win32.Filesystem | |||
[SecurityCritical] | |||
public static void SetAttributesTransacted(KernelTransaction transaction, string path, FileAttributes fileAttributes) | |||
{ | |||
SetAttributesCore(false, transaction, path, fileAttributes, false, PathFormat.RelativePath); | |||
SetAttributesCore(false, transaction, path, fileAttributes, PathFormat.RelativePath); | |||
} | |||
/// <summary>[AlphaFS] Sets the specified <see cref="FileAttributes"/> of the file on the specified path.</summary> | |||
@@ -99,7 +99,7 @@ namespace Alphaleonis.Win32.Filesystem | |||
[SecurityCritical] | |||
public static void SetAttributesTransacted(KernelTransaction transaction, string path, FileAttributes fileAttributes, PathFormat pathFormat) | |||
{ | |||
SetAttributesCore(false, transaction, path, fileAttributes, false, pathFormat); | |||
SetAttributesCore(false, transaction, path, fileAttributes, pathFormat); | |||
} | |||
#endregion // Transacted | |||
@@ -123,16 +123,13 @@ namespace Alphaleonis.Win32.Filesystem | |||
/// <param name="fileAttributes"> | |||
/// The attributes to set for the file or directory. Note that all other values override <see cref="FileAttributes.Normal"/>. | |||
/// </param> | |||
/// <param name="continueOnNotExist"> | |||
/// <see langword="true"/> does not throw an Exception when the file system object does not exist. | |||
/// </param> | |||
/// <param name="pathFormat">Indicates the format of the path parameter(s).</param> | |||
[SecurityCritical] | |||
internal static void SetAttributesCore(bool isFolder, KernelTransaction transaction, string path, FileAttributes fileAttributes, bool continueOnNotExist, PathFormat pathFormat) | |||
internal static void SetAttributesCore(bool isFolder, KernelTransaction transaction, string path, FileAttributes fileAttributes, PathFormat pathFormat) | |||
{ | |||
string pathLp = Path.GetExtendedLengthPathCore(transaction, path, pathFormat, GetFullPathOptions.RemoveTrailingDirectorySeparator | GetFullPathOptions.FullCheck); | |||
var pathLp = Path.GetExtendedLengthPathCore(transaction, path, pathFormat, GetFullPathOptions.RemoveTrailingDirectorySeparator | GetFullPathOptions.FullCheck); | |||
if (!(transaction == null || !NativeMethods.IsAtLeastWindowsVista | |||
var success = transaction == null || !NativeMethods.IsAtLeastWindowsVista | |||
// SetFileAttributes() | |||
// In the ANSI version of this function, the name is limited to MAX_PATH characters. | |||
@@ -140,13 +137,12 @@ namespace Alphaleonis.Win32.Filesystem | |||
// 2013-01-13: MSDN confirms LongPath usage. | |||
? NativeMethods.SetFileAttributes(pathLp, fileAttributes) | |||
: NativeMethods.SetFileAttributesTransacted(pathLp, fileAttributes, transaction.SafeHandle))) | |||
{ | |||
if (continueOnNotExist) | |||
return; | |||
: NativeMethods.SetFileAttributesTransacted(pathLp, fileAttributes, transaction.SafeHandle); | |||
uint lastError = (uint)Marshal.GetLastWin32Error(); | |||
var lastError = (uint) Marshal.GetLastWin32Error(); | |||
if (!success) | |||
{ | |||
switch (lastError) | |||
{ | |||
// MSDN: .NET 3.5+: ArgumentException: FileSystemInfo().Attributes | |||
@@ -155,7 +151,7 @@ namespace Alphaleonis.Win32.Filesystem | |||
case Win32Errors.ERROR_FILE_NOT_FOUND: | |||
if (isFolder) | |||
lastError = (int)Win32Errors.ERROR_PATH_NOT_FOUND; | |||
lastError = (int) Win32Errors.ERROR_PATH_NOT_FOUND; | |||
// MSDN: .NET 3.5+: DirectoryNotFoundException: The specified path is invalid, (for example, it is on an unmapped drive). | |||
// MSDN: .NET 3.5+: FileNotFoundException: The file cannot be found. | |||
@@ -78,7 +78,7 @@ namespace Alphaleonis.Win32.Filesystem | |||
[SecurityCritical] | |||
public FileInfo Replace(string destinationFileName, string destinationBackupFileName, PathFormat pathFormat) | |||
{ | |||
var options = GetFullPathOptions.RemoveTrailingDirectorySeparator | GetFullPathOptions.FullCheck; | |||
const GetFullPathOptions options = GetFullPathOptions.RemoveTrailingDirectorySeparator | GetFullPathOptions.FullCheck; | |||
string destinationFileNameLp = Path.GetExtendedLengthPathCore(Transaction, destinationFileName, pathFormat, options); | |||
string destinationBackupFileNameLp = destinationBackupFileName != null | |||
@@ -105,7 +105,7 @@ namespace Alphaleonis.Win32.Filesystem | |||
[SecurityCritical] | |||
public FileInfo Replace(string destinationFileName, string destinationBackupFileName, bool ignoreMetadataErrors, PathFormat pathFormat) | |||
{ | |||
var options = GetFullPathOptions.RemoveTrailingDirectorySeparator | GetFullPathOptions.FullCheck; | |||
const GetFullPathOptions options = GetFullPathOptions.RemoveTrailingDirectorySeparator | GetFullPathOptions.FullCheck; | |||
string destinationFileNameLp = Path.GetExtendedLengthPathCore(Transaction, destinationFileName, pathFormat, options); | |||
string destinationBackupFileNameLp = destinationBackupFileName != null | |||
@@ -266,7 +266,7 @@ namespace Alphaleonis.Win32.Filesystem | |||
[SecurityCritical] | |||
set | |||
{ | |||
File.SetAttributesCore(IsDirectory, Transaction, LongFullName, value, false, PathFormat.LongFullPath); | |||
File.SetAttributesCore(IsDirectory, Transaction, LongFullName, value, PathFormat.LongFullPath); | |||
Reset(); | |||
} | |||
} | |||
@@ -547,7 +547,7 @@ namespace Alphaleonis.Win32.Filesystem | |||
#region DisplayPath | |||
/// <summary>Returns the path as a string.</summary> | |||
protected internal string DisplayPath { get; set; } | |||
protected internal string DisplayPath { get; protected set; } | |||
#endregion // DisplayPath | |||
@@ -590,7 +590,7 @@ namespace Alphaleonis.Win32.Filesystem | |||
#region IsDirectory | |||
/// <summary>[AlphaFS] The initial "IsDirectory" indicator that was passed to the constructor.</summary> | |||
protected internal bool IsDirectory { get; set; } | |||
protected bool IsDirectory { get; set; } | |||
#endregion // IsDirectory | |||
@@ -604,7 +604,7 @@ namespace Alphaleonis.Win32.Filesystem | |||
#region Transaction | |||
/// <summary>[AlphaFS] Represents the KernelTransaction that was passed to the constructor.</summary> | |||
public KernelTransaction Transaction { get; set; } | |||
protected KernelTransaction Transaction { get; set; } | |||
#endregion // Transaction | |||
@@ -53,7 +53,7 @@ namespace Alphaleonis.Win32.Filesystem | |||
[SuppressMessage("Microsoft.Security", "CA5122:PInvokesShouldNotBeSafeCriticalFxCopRule")] | |||
[DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Unicode, EntryPoint = "DeleteVolumeMountPointW"), SuppressUnmanagedCodeSecurity] | |||
[return: MarshalAs(UnmanagedType.Bool)] | |||
internal extern static bool DeleteVolumeMountPoint([MarshalAs(UnmanagedType.LPWStr)] string lpszVolumeMountPoint); | |||
internal static extern bool DeleteVolumeMountPoint([MarshalAs(UnmanagedType.LPWStr)] string lpszVolumeMountPoint); | |||
/// <summary>Retrieves the name of a volume on a computer. FindFirstVolume is used to begin scanning the volumes of a computer.</summary> | |||
/// <returns> | |||
@@ -64,7 +64,7 @@ namespace Alphaleonis.Win32.Filesystem | |||
/// <remarks>Minimum supported server: Windows Server 2003 [desktop apps only]</remarks> | |||
[SuppressMessage("Microsoft.Security", "CA5122:PInvokesShouldNotBeSafeCriticalFxCopRule")] | |||
[DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Unicode, EntryPoint = "FindFirstVolumeW"), SuppressUnmanagedCodeSecurity] | |||
internal extern static SafeFindVolumeHandle FindFirstVolume(StringBuilder lpszVolumeName, [MarshalAs(UnmanagedType.U4)] uint cchBufferLength); | |||
internal static extern SafeFindVolumeHandle FindFirstVolume(StringBuilder lpszVolumeName, [MarshalAs(UnmanagedType.U4)] uint cchBufferLength); | |||
/// <summary>Retrieves the name of a mounted folder on the specified volume. FindFirstVolumeMountPoint is used to begin scanning the mounted folders on a volume.</summary> | |||
/// <returns> | |||
@@ -75,7 +75,7 @@ namespace Alphaleonis.Win32.Filesystem | |||
/// <remarks>Minimum supported server: Windows Server 2003 [desktop apps only]</remarks> | |||
[SuppressMessage("Microsoft.Security", "CA5122:PInvokesShouldNotBeSafeCriticalFxCopRule")] | |||
[DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Unicode, EntryPoint = "FindFirstVolumeMountPointW"), SuppressUnmanagedCodeSecurity] | |||
internal extern static SafeFindVolumeMountPointHandle FindFirstVolumeMountPoint([MarshalAs(UnmanagedType.LPWStr)] string lpszRootPathName, StringBuilder lpszVolumeMountPoint, [MarshalAs(UnmanagedType.U4)] uint cchBufferLength); | |||
internal static extern SafeFindVolumeMountPointHandle FindFirstVolumeMountPoint([MarshalAs(UnmanagedType.LPWStr)] string lpszRootPathName, StringBuilder lpszVolumeMountPoint, [MarshalAs(UnmanagedType.U4)] uint cchBufferLength); | |||
/// <summary>Continues a volume search started by a call to the FindFirstVolume function. FindNextVolume finds one volume per call.</summary> | |||
/// <returns> | |||
@@ -87,7 +87,7 @@ namespace Alphaleonis.Win32.Filesystem | |||
[SuppressMessage("Microsoft.Security", "CA5122:PInvokesShouldNotBeSafeCriticalFxCopRule")] | |||
[DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Unicode, EntryPoint = "FindNextVolumeW"), SuppressUnmanagedCodeSecurity] | |||
[return: MarshalAs(UnmanagedType.Bool)] | |||
internal extern static bool FindNextVolume(SafeFindVolumeHandle hFindVolume, StringBuilder lpszVolumeName, [MarshalAs(UnmanagedType.U4)] uint cchBufferLength); | |||
internal static extern bool FindNextVolume(SafeFindVolumeHandle hFindVolume, StringBuilder lpszVolumeName, [MarshalAs(UnmanagedType.U4)] uint cchBufferLength); | |||
/// <summary>Continues a mounted folder search started by a call to the FindFirstVolumeMountPoint function. FindNextVolumeMountPoint finds one mounted folder per call.</summary> | |||
/// <returns> | |||
@@ -100,7 +100,7 @@ namespace Alphaleonis.Win32.Filesystem | |||
[SuppressMessage("Microsoft.Security", "CA5122:PInvokesShouldNotBeSafeCriticalFxCopRule")] | |||
[DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Unicode, EntryPoint = "FindNextVolumeMountPointW"), SuppressUnmanagedCodeSecurity] | |||
[return: MarshalAs(UnmanagedType.Bool)] | |||
internal extern static bool FindNextVolumeMountPoint(SafeFindVolumeMountPointHandle hFindVolume, StringBuilder lpszVolumeName, [MarshalAs(UnmanagedType.U4)] uint cchBufferLength); | |||
internal static extern bool FindNextVolumeMountPoint(SafeFindVolumeMountPointHandle hFindVolume, StringBuilder lpszVolumeName, [MarshalAs(UnmanagedType.U4)] uint cchBufferLength); | |||
/// <summary>Closes the specified volume search handle.</summary> | |||
/// <remarks> | |||
@@ -114,7 +114,7 @@ namespace Alphaleonis.Win32.Filesystem | |||
[SuppressMessage("Microsoft.Security", "CA5122:PInvokesShouldNotBeSafeCriticalFxCopRule")] | |||
[DllImport("kernel32.dll", SetLastError = false, CharSet = CharSet.Unicode), SuppressUnmanagedCodeSecurity] | |||
[return: MarshalAs(UnmanagedType.Bool)] | |||
internal extern static bool FindVolumeClose(IntPtr hFindVolume); | |||
internal static extern bool FindVolumeClose(IntPtr hFindVolume); | |||
/// <summary>Closes the specified mounted folder search handle.</summary> | |||
/// <remarks> | |||
@@ -129,7 +129,7 @@ namespace Alphaleonis.Win32.Filesystem | |||
[SuppressMessage("Microsoft.Security", "CA5122:PInvokesShouldNotBeSafeCriticalFxCopRule")] | |||
[DllImport("kernel32.dll", SetLastError = false, CharSet = CharSet.Unicode), SuppressUnmanagedCodeSecurity] | |||
[return: MarshalAs(UnmanagedType.Bool)] | |||
internal extern static bool FindVolumeMountPointClose(IntPtr hFindVolume); | |||
internal static extern bool FindVolumeMountPointClose(IntPtr hFindVolume); | |||
/// <summary> | |||
/// Determines whether a disk drive is a removable, fixed, CD-ROM, RAM disk, or network drive. | |||
@@ -149,7 +149,7 @@ namespace Alphaleonis.Win32.Filesystem | |||
[SuppressMessage("Microsoft.Security", "CA5122:PInvokesShouldNotBeSafeCriticalFxCopRule")] | |||
[DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Unicode, EntryPoint = "GetDriveTypeW"), SuppressUnmanagedCodeSecurity] | |||
[return: MarshalAs(UnmanagedType.U4)] | |||
internal extern static DriveType GetDriveType([MarshalAs(UnmanagedType.LPWStr)] string lpRootPathName); | |||
internal static extern DriveType GetDriveType([MarshalAs(UnmanagedType.LPWStr)] string lpRootPathName); | |||
/// <summary> | |||
/// Retrieves a bitmask representing the currently available disk drives. | |||
@@ -180,7 +180,7 @@ namespace Alphaleonis.Win32.Filesystem | |||
[SuppressMessage("Microsoft.Security", "CA5122:PInvokesShouldNotBeSafeCriticalFxCopRule")] | |||
[DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Unicode, EntryPoint = "GetVolumeInformationW"), SuppressUnmanagedCodeSecurity] | |||
[return: MarshalAs(UnmanagedType.Bool)] | |||
internal extern static bool GetVolumeInformation([MarshalAs(UnmanagedType.LPWStr)] string lpRootPathName, StringBuilder lpVolumeNameBuffer, [MarshalAs(UnmanagedType.U4)] uint nVolumeNameSize, [MarshalAs(UnmanagedType.U4)] out uint lpVolumeSerialNumber, [MarshalAs(UnmanagedType.U4)] out int lpMaximumComponentLength, [MarshalAs(UnmanagedType.U4)] out VolumeInfoAttributes lpFileSystemAttributes, StringBuilder lpFileSystemNameBuffer, [MarshalAs(UnmanagedType.U4)] uint nFileSystemNameSize); | |||
internal static extern bool GetVolumeInformation([MarshalAs(UnmanagedType.LPWStr)] string lpRootPathName, StringBuilder lpVolumeNameBuffer, [MarshalAs(UnmanagedType.U4)] uint nVolumeNameSize, [MarshalAs(UnmanagedType.U4)] out uint lpVolumeSerialNumber, [MarshalAs(UnmanagedType.U4)] out int lpMaximumComponentLength, [MarshalAs(UnmanagedType.U4)] out VolumeInfoAttributes lpFileSystemAttributes, StringBuilder lpFileSystemNameBuffer, [MarshalAs(UnmanagedType.U4)] uint nFileSystemNameSize); | |||
/// <summary>Retrieves information about the file system and volume associated with the specified file.</summary> | |||
/// <returns> | |||
@@ -194,7 +194,7 @@ namespace Alphaleonis.Win32.Filesystem | |||
[SuppressMessage("Microsoft.Security", "CA5122:PInvokesShouldNotBeSafeCriticalFxCopRule")] | |||
[DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Unicode, EntryPoint = "GetVolumeInformationByHandleW"), SuppressUnmanagedCodeSecurity] | |||
[return: MarshalAs(UnmanagedType.Bool)] | |||
internal extern static bool GetVolumeInformationByHandle(SafeFileHandle hFile, StringBuilder lpVolumeNameBuffer, [MarshalAs(UnmanagedType.U4)] uint nVolumeNameSize, [MarshalAs(UnmanagedType.U4)] out uint lpVolumeSerialNumber, [MarshalAs(UnmanagedType.U4)] out int lpMaximumComponentLength, out VolumeInfoAttributes lpFileSystemAttributes, StringBuilder lpFileSystemNameBuffer, [MarshalAs(UnmanagedType.U4)] uint nFileSystemNameSize); | |||
internal static extern bool GetVolumeInformationByHandle(SafeFileHandle hFile, StringBuilder lpVolumeNameBuffer, [MarshalAs(UnmanagedType.U4)] uint nVolumeNameSize, [MarshalAs(UnmanagedType.U4)] out uint lpVolumeSerialNumber, [MarshalAs(UnmanagedType.U4)] out int lpMaximumComponentLength, out VolumeInfoAttributes lpFileSystemAttributes, StringBuilder lpFileSystemNameBuffer, [MarshalAs(UnmanagedType.U4)] uint nFileSystemNameSize); | |||
/// <summary>Retrieves a volume GUID path for the volume that is associated with the specified volume mount point (drive letter, volume GUID path, or mounted folder).</summary> | |||
/// <returns> | |||
@@ -255,7 +255,7 @@ namespace Alphaleonis.Win32.Filesystem | |||
[SuppressMessage("Microsoft.Security", "CA5122:PInvokesShouldNotBeSafeCriticalFxCopRule")] | |||
[DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Unicode, EntryPoint = "SetVolumeLabelW"), SuppressUnmanagedCodeSecurity] | |||
[return: MarshalAs(UnmanagedType.Bool)] | |||
internal extern static bool SetVolumeLabel([MarshalAs(UnmanagedType.LPWStr)] string lpRootPathName, [MarshalAs(UnmanagedType.LPWStr)] string lpVolumeName); | |||
internal static extern bool SetVolumeLabel([MarshalAs(UnmanagedType.LPWStr)] string lpRootPathName, [MarshalAs(UnmanagedType.LPWStr)] string lpVolumeName); | |||
/// <summary>Associates a volume with a drive letter or a directory on another volume.</summary> | |||
/// <remarks>Minimum supported client: Windows XP [desktop apps only].</remarks> | |||
@@ -267,7 +267,7 @@ namespace Alphaleonis.Win32.Filesystem | |||
[SuppressMessage("Microsoft.Security", "CA5122:PInvokesShouldNotBeSafeCriticalFxCopRule")] | |||
[DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Unicode, EntryPoint = "SetVolumeMountPointW"), SuppressUnmanagedCodeSecurity] | |||
[return: MarshalAs(UnmanagedType.Bool)] | |||
internal extern static bool SetVolumeMountPoint([MarshalAs(UnmanagedType.LPWStr)] string lpszVolumeMountPoint, [MarshalAs(UnmanagedType.LPWStr)] string lpszVolumeName); | |||
internal static extern bool SetVolumeMountPoint([MarshalAs(UnmanagedType.LPWStr)] string lpszVolumeMountPoint, [MarshalAs(UnmanagedType.LPWStr)] string lpszVolumeName); | |||
/// <summary>Retrieves information about MS-DOS device names.</summary> | |||
/// <remarks>Minimum supported client: Windows XP [desktop apps only].</remarks> | |||
@@ -67,7 +67,7 @@ namespace Alphaleonis.Win32.Filesystem | |||
if (obj == null || GetType() != obj.GetType()) | |||
return false; | |||
FILETIME other = obj is FILETIME ? (FILETIME)obj : new FILETIME(); | |||
FILETIME other = obj as FILETIME? ?? new FILETIME(); | |||
return (other.dwHighDateTime.Equals(dwHighDateTime) && | |||
other.dwLowDateTime.Equals(dwLowDateTime)); | |||
@@ -63,7 +63,7 @@ namespace Alphaleonis.Win32.Filesystem | |||
public static readonly string StreamSeparator = StreamSeparatorChar.ToString(CultureInfo.CurrentCulture); | |||
/// <summary>[AlphaFS] StreamDataLabel = ':$DATA' Provides a platform-specific Stream :$DATA label.</summary> | |||
public static readonly string StreamDataLabel = ":$DATA"; | |||
public const string StreamDataLabel = ":$DATA"; | |||
/// <summary>[AlphaFS] StringTerminatorChar = '\0' String Terminator Suffix.</summary> | |||
public const char StringTerminatorChar = '\0'; | |||
@@ -357,10 +357,9 @@ namespace Alphaleonis.Win32.Filesystem | |||
if (path.StartsWith(LongPathPrefix, StringComparison.OrdinalIgnoreCase)) | |||
return GetLongPathCore(path.Substring(0, rootLengthPath), GetFullPathOptions.None); | |||
if (path.StartsWith(LongPathUncPrefix, StringComparison.OrdinalIgnoreCase)) | |||
return GetLongPathCore(pathRp.Substring(0, rootLengthPathRp), GetFullPathOptions.None); | |||
return path.Substring(0, rootLengthPath); | |||
return path.StartsWith(LongPathUncPrefix, StringComparison.OrdinalIgnoreCase) | |||
? GetLongPathCore(pathRp.Substring(0, rootLengthPathRp), GetFullPathOptions.None) | |||
: path.Substring(0, rootLengthPath); | |||
} | |||
#endregion // GetPathRoot | |||
@@ -656,15 +656,12 @@ namespace Alphaleonis.Win32.Filesystem | |||
[SecurityCritical] | |||
public static bool PathFileExists(string path) | |||
{ | |||
if (Utils.IsNullOrWhiteSpace(path)) | |||
return false; | |||
// PathFileExists() | |||
// In the ANSI version of this function, the name is limited to 248 characters. | |||
// To extend this limit to 32,767 wide characters, call the Unicode version of the function and prepend "\\?\" to the path. | |||
// 2013-01-13: MSDN does not confirm LongPath usage but a Unicode version of this function exists. | |||
return NativeMethods.PathFileExists(Path.GetFullPathCore(null, path, GetFullPathOptions.AsLongPath | GetFullPathOptions.FullCheck | GetFullPathOptions.ContinueOnNonExist)); | |||
return !Utils.IsNullOrWhiteSpace(path) && NativeMethods.PathFileExists(Path.GetFullPathCore(null, path, GetFullPathOptions.AsLongPath | GetFullPathOptions.FullCheck | GetFullPathOptions.ContinueOnNonExist)); | |||
} | |||
@@ -175,7 +175,7 @@ namespace Alphaleonis.Win32.Filesystem | |||
// The deviceName cannot have a trailing backslash. | |||
deviceName = Path.RemoveTrailingDirectorySeparator(deviceName, false); | |||
var searchFilter = (deviceName != null); | |||
var searchFilter = deviceName != null; | |||
// Only process options if a device is supplied. | |||
if (searchFilter) | |||
@@ -49,7 +49,7 @@ namespace Alphaleonis.Win32.Network | |||
/// <summary>RESOURCETYPE_PRINT | |||
/// <para>All print resources.</para> | |||
/// </summary> | |||
Print = 2, | |||
Print = 2 | |||
} | |||
} | |||
} |
@@ -41,6 +41,6 @@ namespace Alphaleonis.Win32.Network | |||
Info503 = 503, | |||
/// <summary>Contains information about the shared resource.</summary> | |||
Info1005 = 1005, | |||
Info1005 = 1005 | |||
} | |||
} |
@@ -86,6 +86,6 @@ namespace Alphaleonis.Win32.Network | |||
/// <remarks>Windows 7, Windows Server 2008 R2, Windows Vista, Windows Server 2008, and Windows Server 2003: This flag is not supported.</remarks> | |||
[SuppressMessage("Microsoft.Naming", "CA1709:IdentifiersShouldBeCasedCorrectly", MessageId = "Ca")] | |||
[SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Ca")] | |||
EnableCa = 16384, | |||
EnableCa = 16384 | |||
} | |||
} |
@@ -199,7 +199,7 @@ namespace Alphaleonis.Win32.Network | |||
totalEntries = 0; | |||
// When host == null, the local computer is used. | |||
// However, the resulting OpenResourceInfo.Host property will be empty. | |||
// However, the resulting Host property will be empty. | |||
// So, explicitly state Environment.MachineName to prevent this. | |||
// Furthermore, the UNC prefix: \\ is not required and always removed. | |||
string stripUnc = Utils.IsNullOrWhiteSpace(host) ? Environment.MachineName : Path.GetRegularPathCore(host, GetFullPathOptions.CheckInvalidPathChars, false).Replace(Path.UncPrefix, string.Empty); | |||
@@ -233,7 +233,7 @@ namespace Alphaleonis.Win32.Network | |||
totalEntries = 0; | |||
// When host == null, the local computer is used. | |||
// However, the resulting OpenResourceInfo.Host property will be empty. | |||
// However, the resulting Host property will be empty. | |||
// So, explicitly state Environment.MachineName to prevent this. | |||
// Furthermore, the UNC prefix: \\ is not required and always removed. | |||
string stripUnc = Utils.IsNullOrWhiteSpace(domain) ? NativeMethods.ComputerDomain : Path.GetRegularPathCore(domain, GetFullPathOptions.CheckInvalidPathChars, false).Replace(Path.UncPrefix, string.Empty); | |||
@@ -73,10 +73,9 @@ namespace Alphaleonis.Win32.Network | |||
(FunctionData functionData, out SafeGlobalMemoryBufferHandle buffer, int prefMaxLen, out uint entriesRead, out uint totalEntries, out uint resume) => | |||
{ | |||
// When host == null, the local computer is used. | |||
// However, the resulting OpenResourceInfo.Host property will be empty. | |||
// However, the resulting Host property will be empty. | |||
// So, explicitly state Environment.MachineName to prevent this. | |||
// Furthermore, the UNC prefix: \\ is not required and always removed. | |||
string stripUnc = Utils.IsNullOrWhiteSpace(host) ? Environment.MachineName : Path.GetRegularPathCore(host, GetFullPathOptions.CheckInvalidPathChars, false).Replace(Path.UncPrefix, string.Empty); | |||
return NativeMethods.NetServerDiskEnum(stripUnc, 0, out buffer, NativeMethods.MaxPreferredLength, out entriesRead, out totalEntries, out resume); | |||
@@ -98,7 +98,7 @@ namespace Alphaleonis.Win32.Network | |||
(FunctionData functionData, out SafeGlobalMemoryBufferHandle buffer, int prefMaxLen, out uint entriesRead, out uint totalEntries, out uint resumeHandle) => | |||
{ | |||
// When host == null, the local computer is used. | |||
// However, the resulting OpenResourceInfo.Host property will be empty. | |||
// However, the resulting Host property will be empty. | |||
// So, explicitly state Environment.MachineName to prevent this. | |||
// Furthermore, the UNC prefix: \\ is not required and always removed. | |||
string stripUnc = Utils.IsNullOrWhiteSpace(host) ? Environment.MachineName : Path.GetRegularPathCore(host, GetFullPathOptions.CheckInvalidPathChars, false).Replace(Path.UncPrefix, string.Empty); | |||
@@ -168,7 +168,7 @@ namespace Alphaleonis.Win32.Network | |||
[SecurityCritical] | |||
public static ShareInfo GetShareInfo(string uncPath, bool continueOnException) | |||
{ | |||
string[] unc = GetHostShareFromPath(uncPath); | |||
var unc = GetHostShareFromPath(uncPath); | |||
return GetShareInfoCore(ShareInfoLevel.Info503, unc[0], unc[1], continueOnException); | |||
} | |||
@@ -180,7 +180,7 @@ namespace Alphaleonis.Win32.Network | |||
[SecurityCritical] | |||
public static ShareInfo GetShareInfo(ShareInfoLevel shareLevel, string uncPath, bool continueOnException) | |||
{ | |||
string[] unc = GetHostShareFromPath(uncPath); | |||
var unc = GetHostShareFromPath(uncPath); | |||
return GetShareInfoCore(shareLevel, unc[0], unc[1], continueOnException); | |||
} | |||
@@ -213,7 +213,7 @@ namespace Alphaleonis.Win32.Network | |||
#region EnumerateOpenConnectionsCore | |||
/// <summary>Enumerates open connections from the specified host.</summary> | |||
/// <summary>Enumerates open connections from the specified host and <paramref name="share"/>.</summary> | |||
/// <returns><see cref="OpenConnectionInfo"/> connection information from the specified <paramref name="host"/>.</returns> | |||
/// <exception cref="ArgumentNullException"/> | |||
/// <exception cref="NetworkInformationException"/> | |||
@@ -241,6 +241,7 @@ namespace Alphaleonis.Win32.Network | |||
return NativeMethods.NetConnectionEnum(stripUnc, functionData.ExtraData1, 1, out buffer, NativeMethods.MaxPreferredLength, out entriesRead, out totalEntries, out resumeHandle); | |||
}, | |||
continueOnException); | |||
} | |||
@@ -260,16 +261,14 @@ namespace Alphaleonis.Win32.Network | |||
internal static IEnumerable<ShareInfo> EnumerateSharesCore(string host, ShareType shareType, bool continueOnException) | |||
{ | |||
// When host == null, the local computer is used. | |||
// However, the resulting OpenResourceInfo.Host property will be empty. | |||
// However, the resulting Host property will be empty. | |||
// So, explicitly state Environment.MachineName to prevent this. | |||
// Furthermore, the UNC prefix: \\ is not required and always removed. | |||
string stripUnc = Utils.IsNullOrWhiteSpace(host) | |||
? Environment.MachineName | |||
: Path.GetRegularPathCore(host, GetFullPathOptions.CheckInvalidPathChars, false).Replace(Path.UncPrefix, string.Empty); | |||
var stripUnc = Utils.IsNullOrWhiteSpace(host) ? Environment.MachineName : Path.GetRegularPathCore(host, GetFullPathOptions.CheckInvalidPathChars, false).Replace(Path.UncPrefix, string.Empty); | |||
var fd = new FunctionData(); | |||
bool hasItems = false; | |||
bool yieldAll = shareType == ShareType.All; | |||
var hasItems = false; | |||
var yieldAll = shareType == ShareType.All; | |||
// Try SHARE_INFO_503 structure. | |||
foreach (var si in EnumerateNetworkObjectCore(fd, (NativeMethods.SHARE_INFO_503 structure, SafeGlobalMemoryBufferHandle buffer) => | |||
@@ -323,14 +322,12 @@ namespace Alphaleonis.Win32.Network | |||
return null; | |||
// When host == null, the local computer is used. | |||
// However, the resulting OpenResourceInfo.Host property will be empty. | |||
// However, the resulting Host property will be empty. | |||
// So, explicitly state Environment.MachineName to prevent this. | |||
// Furthermore, the UNC prefix: \\ is not required and always removed. | |||
string stripUnc = Utils.IsNullOrWhiteSpace(host) | |||
? Environment.MachineName | |||
: Path.GetRegularPathCore(host, GetFullPathOptions.CheckInvalidPathChars, false).Replace(Path.UncPrefix, string.Empty); | |||
var stripUnc = Utils.IsNullOrWhiteSpace(host) ? Environment.MachineName : Path.GetRegularPathCore(host, GetFullPathOptions.CheckInvalidPathChars, false).Replace(Path.UncPrefix, string.Empty); | |||
bool fallback = false; | |||
var fallback = false; | |||
startNetShareGetInfo: | |||
@@ -338,7 +335,7 @@ namespace Alphaleonis.Win32.Network | |||
SafeGlobalMemoryBufferHandle safeBuffer; | |||
uint structureLevel = Convert.ToUInt16(shareLevel, CultureInfo.InvariantCulture); | |||
uint lastError = NativeMethods.NetShareGetInfo(stripUnc, share, structureLevel, out safeBuffer); | |||
var lastError = NativeMethods.NetShareGetInfo(stripUnc, share, structureLevel, out safeBuffer); | |||
using (safeBuffer) | |||
{ | |||
@@ -19,7 +19,6 @@ | |||
* THE SOFTWARE. | |||
*/ | |||
using System; | |||
using System.Diagnostics.CodeAnalysis; | |||
using System.Runtime.InteropServices; | |||
using System.Security; | |||
@@ -1,7 +1,7 @@ | |||
//------------------------------------------------------------------------------ | |||
// <auto-generated> | |||
// This code was generated by a tool. | |||
// Runtime Version:4.0.30319.42000 | |||
// Runtime Version:4.0.30319.34209 | |||
// | |||
// Changes to this file may cause incorrect behavior and will be lost if | |||
// the code is regenerated. | |||
@@ -30,14 +30,13 @@ namespace Alphaleonis.Win32 | |||
{ | |||
#region Private Fields | |||
private int m_capacity; | |||
private readonly int m_capacity; | |||
#endregion | |||
#region Constructors | |||
protected SafeNativeMemoryBufferHandle(bool ownsHandle) | |||
: base(ownsHandle) | |||
protected SafeNativeMemoryBufferHandle(bool ownsHandle) : base(ownsHandle) | |||
{ | |||
} | |||
@@ -42,8 +42,7 @@ namespace Alphaleonis.Win32.Security | |||
private ulong m_hash; | |||
/// <summary>Initializes a new instance of <see cref="Crc64"/> </summary> | |||
public Crc64() | |||
: this(Iso3309Polynomial, DefaultSeed) | |||
public Crc64() : this(Iso3309Polynomial, DefaultSeed) | |||
{ | |||
} | |||
@@ -53,7 +52,7 @@ namespace Alphaleonis.Win32.Security | |||
private Crc64(ulong polynomial, ulong seed) | |||
{ | |||
m_table = InitializeTable(polynomial); | |||
this.m_seed = m_hash = seed; | |||
m_seed = m_hash = seed; | |||
} | |||
/// <summary> | |||
@@ -106,11 +105,13 @@ namespace Alphaleonis.Win32.Security | |||
private static ulong CalculateHash(ulong seed, ulong[] table, IList<byte> buffer, int start, int size) | |||
{ | |||
var hash = seed; | |||
for (var i = start; i < start + size; i++) | |||
for (var i = start; i < start + size; i++) | |||
unchecked | |||
{ | |||
hash = (hash >> 8) ^ table[(buffer[i] ^ hash) & 0xff]; | |||
} | |||
return hash; | |||
} | |||
@@ -151,12 +152,11 @@ namespace Alphaleonis.Win32.Security | |||
var createTable = new ulong[256]; | |||
for (var i = 0; i < 256; ++i) | |||
{ | |||
var entry = (ulong)i; | |||
var entry = (ulong) i; | |||
for (var j = 0; j < 8; ++j) | |||
if ((entry & 1) == 1) | |||
entry = (entry >> 1) ^ polynomial; | |||
else | |||
entry = entry >> 1; | |||
entry = (entry & 1) == 1 ? (entry >> 1) ^ polynomial : entry >> 1; | |||
createTable[i] = entry; | |||
} | |||
@@ -43,7 +43,7 @@ namespace Alphaleonis.Win32.Security | |||
if (privilegeName == null) | |||
throw new ArgumentNullException("privilegeName"); | |||
_mPrivilege = privilegeName; | |||
EnabledPrivilege = privilegeName; | |||
AdjustPrivilege(true); | |||
} | |||
@@ -55,12 +55,12 @@ namespace Alphaleonis.Win32.Security | |||
{ | |||
try | |||
{ | |||
if (_mPrivilege != null) | |||
if (EnabledPrivilege != null) | |||
AdjustPrivilege(false); | |||
} | |||
finally | |||
{ | |||
_mPrivilege = null; | |||
EnabledPrivilege = null; | |||
} | |||
} | |||
@@ -71,31 +71,23 @@ namespace Alphaleonis.Win32.Security | |||
{ | |||
using (WindowsIdentity currentIdentity = WindowsIdentity.GetCurrent(TokenAccessLevels.Query | TokenAccessLevels.AdjustPrivileges)) | |||
{ | |||
if (currentIdentity != null) | |||
{ | |||
IntPtr hToken = currentIdentity.Token; | |||
TokenPrivileges newPrivilege = new TokenPrivileges(); | |||
TokenPrivileges mOldPrivilege = new TokenPrivileges(); | |||
newPrivilege.PrivilegeCount = 1; | |||
newPrivilege.Luid = Filesystem.NativeMethods.LongToLuid(_mPrivilege.LookupLuid()); | |||
newPrivilege.Attributes = (uint)(enable ? 2 : 0); // 2 = SePrivilegeEnabled; | |||
IntPtr hToken = currentIdentity.Token; | |||
TokenPrivileges newPrivilege = new TokenPrivileges(); | |||
TokenPrivileges mOldPrivilege = new TokenPrivileges(); | |||
newPrivilege.PrivilegeCount = 1; | |||
newPrivilege.Luid = Filesystem.NativeMethods.LongToLuid(EnabledPrivilege.LookupLuid()); | |||
newPrivilege.Attributes = (uint)(enable ? 2 : 0); // 2 = SePrivilegeEnabled; | |||
uint length; | |||
if (!NativeMethods.AdjustTokenPrivileges(hToken, false, ref newPrivilege, (uint) Marshal.SizeOf(mOldPrivilege), out mOldPrivilege, out length)) | |||
NativeError.ThrowException(Marshal.GetLastWin32Error()); | |||
uint length; | |||
if (!NativeMethods.AdjustTokenPrivileges(hToken, false, ref newPrivilege, (uint) Marshal.SizeOf(mOldPrivilege), out mOldPrivilege, out length)) | |||
NativeError.ThrowException(Marshal.GetLastWin32Error()); | |||
// If no privilege was changed, we don't want to reset it. | |||
if (mOldPrivilege.PrivilegeCount == 0) | |||
_mPrivilege = null; | |||
} | |||
// If no privilege was changed, we don't want to reset it. | |||
if (mOldPrivilege.PrivilegeCount == 0) | |||
EnabledPrivilege = null; | |||
} | |||
} | |||
public Privilege EnabledPrivilege | |||
{ | |||
get { return _mPrivilege; } | |||
} | |||
private Privilege _mPrivilege; | |||
public Privilege EnabledPrivilege { get; private set; } | |||
} | |||
} |
@@ -490,5 +490,5 @@ namespace Alphaleonis.Win32.Security | |||
} | |||
#endregion // Privilege | |||
}; | |||
} | |||
} |
@@ -222,8 +222,8 @@ namespace Alphaleonis.Win32 | |||
//public const uint ERROR_SIGNAL_REFUSED = 156; | |||
//public const uint ERROR_DISCARDED = 157; | |||
/// <summary>(158) The segment is already unlocked.</summary> | |||
public const uint ERROR_NOT_LOCKED = 158; | |||
// <summary>(158) The segment is already unlocked.</summary> | |||
//public const uint ERROR_NOT_LOCKED = 158; | |||
//public const uint ERROR_BAD_THREADID_ADDR = 159; | |||
//public const uint ERROR_BAD_ARGUMENTS = 160; | |||
@@ -259,7 +259,7 @@ namespace Alphaleonis.Win32 | |||
//public const uint ERROR_INFLOOP_IN_RELOC_CHAIN = 202; | |||
/// <summary>(203) The system could not find the environment option that was entered.</summary> | |||
public const uint ERROR_ENVVAR_NOT_FOUND = 203; | |||
//public const uint ERROR_ENVVAR_NOT_FOUND = 203; | |||
//public const uint ERROR_NO_SIGNAL_SENT = 205; | |||
//public const uint ERROR_FILENAME_EXCED_RANGE = 206; | |||
@@ -320,7 +320,7 @@ namespace Alphaleonis.Win32 | |||
//public const uint ERROR_IO_INCOMPLETE = 996; | |||
/// <summary>(997) Overlapped I/O operation is in progress.</summary> | |||
public const uint ERROR_IO_PENDING = 997; | |||
//public const uint ERROR_IO_PENDING = 997; | |||
//public const uint ERROR_NOACCESS = 998; | |||
//public const uint ERROR_SWAPERROR = 999; | |||
@@ -449,7 +449,7 @@ namespace Alphaleonis.Win32 | |||
//public const uint ERROR_JOURNAL_ENTRY_DELETED = 1181; | |||
/// <summary>(1200) The specified device name is invalid.</summary> | |||
public const uint ERROR_BAD_DEVICE = 1200; | |||
//public const uint ERROR_BAD_DEVICE = 1200; | |||
//public const uint ERROR_CONNECTION_UNAVAIL = 1201; | |||
//public const uint ERROR_DEVICE_ALREADY_REMEMBERED = 1202; | |||
@@ -460,7 +460,7 @@ namespace Alphaleonis.Win32 | |||
//public const uint ERROR_NOT_CONTAINER = 1207; | |||
/// <summary>(1208) An extended error has occurred.</summary> | |||
public const uint ERROR_EXTENDED_ERROR = 1208; | |||
//public const uint ERROR_EXTENDED_ERROR = 1208; | |||
//public const uint ERROR_INVALID_GROUPNAME = 1209; | |||
//public const uint ERROR_INVALID_COMPUTERNAME = 1210; | |||
@@ -477,7 +477,7 @@ namespace Alphaleonis.Win32 | |||
//public const uint ERROR_DUP_DOMAINNAME = 1221; | |||
/// <summary>(1222) The network is not present or not started.</summary> | |||
public const uint ERROR_NO_NETWORK = 1222; | |||
//public const uint ERROR_NO_NETWORK = 1222; | |||
//public const uint ERROR_CANCELLED = 1223; | |||
//public const uint ERROR_USER_MAPPED_FILE = 1224; | |||
@@ -3226,7 +3226,7 @@ namespace Alphaleonis.Win32 | |||
// http://msdn.microsoft.com/en-us/library/windows/desktop/aa370674%28v=vs.85%29.aspx | |||
/// <summary>(0) The operation completed successfully.</summary> | |||
public const uint NERR_Success = 0; | |||
public const uint NERR_Success = ERROR_SUCCESS; | |||
///// <summary>The workstation driver is not installed.</summary> | |||
//public const uint NERR_NetNotStarted = 2102; | |||
@@ -3559,7 +3559,7 @@ namespace Alphaleonis.Win32 | |||
//public const uint NERR_SyncRequired = 2249; | |||
/// <summary>(2250) The network connection could not be found.</summary> | |||
public const uint NERR_UseNotFound = 2250; | |||
//public const uint NERR_UseNotFound = 2250; | |||
///// <summary>This asg_type is invalid.</summary> | |||
//public const uint NERR_BadAsgType = 2251; | |||
@@ -3646,7 +3646,7 @@ namespace Alphaleonis.Win32 | |||
//public const uint NERR_MultipleNets = 2300; | |||
/// <summary>(2310) This shared resource does not exist.</summary> | |||
public const uint NERR_NetNameNotFound = 2310; | |||
//public const uint NERR_NetNameNotFound = 2310; | |||
///// <summary>This device is not shared.</summary> | |||
//public const uint NERR_DeviceNotShared = 2311; | |||
@@ -1,3 +1,3 @@ | |||
<?xml version="1.0"?> | |||
<configuration> | |||
<startup><supportedRuntime version="v2.0.50727" sku="Client"/></startup></configuration> | |||
<startup><supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.0,Profile=Client"/></startup></configuration> |
@@ -22,7 +22,7 @@ | |||
<DebugSymbols>true</DebugSymbols> | |||
<DebugType>full</DebugType> | |||
<Optimize>false</Optimize> | |||
<OutputPath>..\..\..\..\..\Program Files\WindowsPowerShell\Modules\NTFSSecurity\</OutputPath> | |||
<OutputPath>..\..\..\..\..\..\Program Files\WindowsPowerShell\Modules\NTFSSecurity\</OutputPath> | |||
<DefineConstants>TRACE;DEBUG</DefineConstants> | |||
<ErrorReport>prompt</ErrorReport> | |||
<WarningLevel>4</WarningLevel> | |||