@@ -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> | <AssemblyOriginatorKeyFile>..\AlphaFS.snk</AssemblyOriginatorKeyFile> | ||||
<CodeAnalysisRuleSet>AlphaFS.ruleset</CodeAnalysisRuleSet> | <CodeAnalysisRuleSet>AlphaFS.ruleset</CodeAnalysisRuleSet> | ||||
<DelaySign>false</DelaySign> | <DelaySign>false</DelaySign> | ||||
<TargetFrameworkProfile>Client</TargetFrameworkProfile> | |||||
<TargetFrameworkProfile /> | |||||
</PropertyGroup> | </PropertyGroup> | ||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' "> | <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' "> | ||||
<DebugSymbols>true</DebugSymbols> | <DebugSymbols>true</DebugSymbols> | ||||
@@ -387,7 +387,7 @@ | |||||
--> | --> | ||||
<ProjectExtensions> | <ProjectExtensions> | ||||
<VisualStudio> | <VisualStudio> | ||||
<UserProperties StartDate="20080813" AssemblyFileVersion="0" AssemblyVersion="0" Reset="1" /> | |||||
<UserProperties Reset="1" AssemblyVersion="0" AssemblyFileVersion="0" StartDate="20080813" /> | |||||
</VisualStudio> | </VisualStudio> | ||||
</ProjectExtensions> | </ProjectExtensions> | ||||
</Project> | </Project> |
@@ -19,8 +19,6 @@ | |||||
* THE SOFTWARE. | * THE SOFTWARE. | ||||
*/ | */ | ||||
using System.Reflection; | using System.Reflection; | ||||
using System.Runtime.CompilerServices; | |||||
using System.Runtime.InteropServices; | |||||
using System.Resources; | using System.Resources; | ||||
[assembly: AssemblyCompany("")] | [assembly: AssemblyCompany("")] | ||||
@@ -29,7 +27,7 @@ using System.Resources; | |||||
[assembly: AssemblyTrademark("")] | [assembly: AssemblyTrademark("")] | ||||
[assembly: AssemblyVersion("2.1.0.0")] | [assembly: AssemblyVersion("2.1.0.0")] | ||||
[assembly: AssemblyFileVersion("2.1.0.0")] | |||||
[assembly: AssemblyFileVersion("2.1.2.0")] | |||||
[assembly: AssemblyInformationalVersion("2.0")] | [assembly: AssemblyInformationalVersion("2.0")] | ||||
[assembly: NeutralResourcesLanguageAttribute("en-US")] | [assembly: NeutralResourcesLanguageAttribute("en-US")] | ||||
@@ -19,8 +19,6 @@ | |||||
* THE SOFTWARE. | * THE SOFTWARE. | ||||
*/ | */ | ||||
using System; | |||||
namespace Alphaleonis.Win32.Filesystem | namespace Alphaleonis.Win32.Filesystem | ||||
{ | { | ||||
/// <summary>Callback used by CopyFileXxx and MoveFileXxx to report progress about the copy/move operation.</summary> | /// <summary>Callback used by CopyFileXxx and MoveFileXxx to report progress about the copy/move operation.</summary> | ||||
@@ -19,9 +19,6 @@ | |||||
* THE SOFTWARE. | * THE SOFTWARE. | ||||
*/ | */ | ||||
using System.ComponentModel; | |||||
using System.Diagnostics.CodeAnalysis; | |||||
namespace Alphaleonis.Win32.Filesystem | namespace Alphaleonis.Win32.Filesystem | ||||
{ | { | ||||
/// <summary>Class for CopyMoveResult that contains the results for the Copy or Move action.</summary> | /// <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; } | 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> | /// <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> | /// <value><see langword="true"/> when the Copy/Move action was canceled. Otherwise <see langword="false"/>.</value> | ||||
public bool IsCanceled { get; internal set; } | public bool IsCanceled { get; internal set; } | ||||
@@ -20,6 +20,7 @@ | |||||
*/ | */ | ||||
using System; | using System; | ||||
using System.Collections.Generic; | |||||
using System.Diagnostics.CodeAnalysis; | using System.Diagnostics.CodeAnalysis; | ||||
using System.IO; | using System.IO; | ||||
using System.Security; | using System.Security; | ||||
@@ -804,10 +805,16 @@ namespace Alphaleonis.Win32.Filesystem | |||||
var sourcePathLp = sourcePath; | var sourcePathLp = sourcePath; | ||||
var destinationPathLp = destinationPath; | 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(sourcePathLp, true, true); | ||||
Path.CheckSupportedPathFormat(destinationPathLp, 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. | // MSDN: .NET3.5+: IOException: The sourceDirName and destDirName parameters refer to the same file or directory. | ||||
if (sourcePathLp.Equals(destinationPathLp, StringComparison.OrdinalIgnoreCase)) | if (sourcePathLp.Equals(destinationPathLp, StringComparison.OrdinalIgnoreCase)) | ||||
NativeError.ThrowException(Win32Errors.ERROR_SAME_DRIVE, destinationPathLp); | 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) | 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 | #endregion // Setup | ||||
#region Copy | #region Copy | ||||
@@ -900,45 +898,56 @@ namespace Alphaleonis.Win32.Filesystem | |||||
{ | { | ||||
CreateDirectoryCore(transaction, destinationPathLp, null, null, false, PathFormat.LongFullPath); | 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) | if (fsei.IsDirectory) | ||||
{ | |||||
CreateDirectoryCore(transaction, newDestinationPathLp, null, null, false, PathFormat.LongFullPath); | |||||
dirs.Enqueue(fsei.LongFullPath); | |||||
cmr.TotalFolders++; | 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.TotalFiles++; | ||||
cmr.TotalBytes += fsei.FileSize; | 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. | // Remove source folder. | ||||
if (emulateMove && cmr.ErrorCode == Win32Errors.ERROR_SUCCESS) | 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 | #endregion // Copy | ||||
@@ -950,7 +959,7 @@ namespace Alphaleonis.Win32.Filesystem | |||||
{ | { | ||||
// MoveOptions.ReplaceExisting: This value cannot be used if lpNewFileName or lpExistingFileName names a directory. | // MoveOptions.ReplaceExisting: This value cannot be used if lpNewFileName or lpExistingFileName names a directory. | ||||
if (((MoveOptions) moveOptions & MoveOptions.ReplaceExisting) != 0) | 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. | // Moves a file or directory, including its children. | ||||
@@ -961,7 +970,7 @@ namespace Alphaleonis.Win32.Filesystem | |||||
#endregion // Move | #endregion // Move | ||||
return cmr; | |||||
return isMove ? null : cmr; | |||||
} | } | ||||
#endregion // Internal Methods | #endregion // Internal Methods | ||||
@@ -20,6 +20,7 @@ | |||||
*/ | */ | ||||
using System; | using System; | ||||
using System.Collections.Generic; | |||||
using System.Diagnostics.CodeAnalysis; | using System.Diagnostics.CodeAnalysis; | ||||
using System.Globalization; | using System.Globalization; | ||||
using System.IO; | using System.IO; | ||||
@@ -44,7 +45,7 @@ namespace Alphaleonis.Win32.Filesystem | |||||
[SecurityCritical] | [SecurityCritical] | ||||
public static void Delete(string path) | 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> | /// <summary>Deletes the specified directory and, if indicated, any subdirectories in the directory.</summary> | ||||
@@ -60,7 +61,7 @@ namespace Alphaleonis.Win32.Filesystem | |||||
[SecurityCritical] | [SecurityCritical] | ||||
public static void Delete(string path, bool recursive) | 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 | #endregion // .NET | ||||
@@ -78,11 +79,10 @@ namespace Alphaleonis.Win32.Filesystem | |||||
[SecurityCritical] | [SecurityCritical] | ||||
public static void Delete(string path, PathFormat pathFormat) | 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> | /// <summary>[AlphaFS] Deletes the specified directory and, if indicated, any subdirectories in the directory.</summary> | ||||
/// <exception cref="ArgumentException"/> | /// <exception cref="ArgumentException"/> | ||||
/// <exception cref="ArgumentNullException"/> | /// <exception cref="ArgumentNullException"/> | ||||
@@ -97,11 +97,10 @@ namespace Alphaleonis.Win32.Filesystem | |||||
[SecurityCritical] | [SecurityCritical] | ||||
public static void Delete(string path, bool recursive, PathFormat pathFormat) | 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> | /// <summary>[AlphaFS] Deletes the specified directory and, if indicated, any subdirectories in the directory.</summary> | ||||
/// <exception cref="ArgumentException"/> | /// <exception cref="ArgumentException"/> | ||||
/// <exception cref="ArgumentNullException"/> | /// <exception cref="ArgumentNullException"/> | ||||
@@ -116,7 +115,7 @@ namespace Alphaleonis.Win32.Filesystem | |||||
[SecurityCritical] | [SecurityCritical] | ||||
public static void Delete(string path, bool recursive, bool ignoreReadOnly) | 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> | /// <summary>[AlphaFS] Deletes the specified directory and, if indicated, any subdirectories in the directory.</summary> | ||||
@@ -134,9 +133,10 @@ namespace Alphaleonis.Win32.Filesystem | |||||
[SecurityCritical] | [SecurityCritical] | ||||
public static void Delete(string path, bool recursive, bool ignoreReadOnly, PathFormat pathFormat) | 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 | #region Transactional | ||||
/// <summary>[AlphaFS] Deletes an empty directory from a specified path.</summary> | /// <summary>[AlphaFS] Deletes an empty directory from a specified path.</summary> | ||||
@@ -152,7 +152,7 @@ namespace Alphaleonis.Win32.Filesystem | |||||
[SecurityCritical] | [SecurityCritical] | ||||
public static void DeleteTransacted(KernelTransaction transaction, string path) | 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> | /// <summary>[AlphaFS] Deletes an empty directory from a specified path.</summary> | ||||
@@ -169,11 +169,10 @@ namespace Alphaleonis.Win32.Filesystem | |||||
[SecurityCritical] | [SecurityCritical] | ||||
public static void DeleteTransacted(KernelTransaction transaction, string path, PathFormat pathFormat) | 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> | /// <summary>[AlphaFS] Deletes the specified directory and, if indicated, any subdirectories in the directory.</summary> | ||||
/// <exception cref="ArgumentException"/> | /// <exception cref="ArgumentException"/> | ||||
/// <exception cref="ArgumentNullException"/> | /// <exception cref="ArgumentNullException"/> | ||||
@@ -188,7 +187,7 @@ namespace Alphaleonis.Win32.Filesystem | |||||
[SecurityCritical] | [SecurityCritical] | ||||
public static void DeleteTransacted(KernelTransaction transaction, string path, bool recursive) | 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> | /// <summary>[AlphaFS] Deletes the specified directory and, if indicated, any subdirectories in the directory.</summary> | ||||
@@ -206,10 +205,9 @@ namespace Alphaleonis.Win32.Filesystem | |||||
[SecurityCritical] | [SecurityCritical] | ||||
public static void DeleteTransacted(KernelTransaction transaction, string path, bool recursive, PathFormat pathFormat) | 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> | /// <summary>[AlphaFS] Deletes the specified directory and, if indicated, any subdirectories in the directory.</summary> | ||||
/// <exception cref="ArgumentException"/> | /// <exception cref="ArgumentException"/> | ||||
@@ -226,7 +224,7 @@ namespace Alphaleonis.Win32.Filesystem | |||||
[SecurityCritical] | [SecurityCritical] | ||||
public static void DeleteTransacted(KernelTransaction transaction, string path, bool recursive, bool ignoreReadOnly) | 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> | /// <summary>[AlphaFS] Deletes the specified directory and, if indicated, any subdirectories in the directory.</summary> | ||||
@@ -245,11 +243,12 @@ namespace Alphaleonis.Win32.Filesystem | |||||
[SecurityCritical] | [SecurityCritical] | ||||
public static void DeleteTransacted(KernelTransaction transaction, string path, bool recursive, bool ignoreReadOnly, PathFormat pathFormat) | 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 | #endregion // Transactional | ||||
#region Internal Methods | #region Internal Methods | ||||
/// <summary>Deletes the specified directory and, if indicated, any subdirectories in the directory.</summary> | /// <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="NotSupportedException"/> | ||||
/// <exception cref="UnauthorizedAccessException"/> | /// <exception cref="UnauthorizedAccessException"/> | ||||
/// <exception cref="DirectoryReadOnlyException"/> | /// <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="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="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="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> | /// <param name="pathFormat">Indicates the format of the path parameter(s).</param> | ||||
[SuppressMessage("Microsoft.Maintainability", "CA1502:AvoidExcessiveComplexity")] | [SuppressMessage("Microsoft.Maintainability", "CA1502:AvoidExcessiveComplexity")] | ||||
[SecurityCritical] | [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 | #region Setup | ||||
if (pathFormat == PathFormat.RelativePath) | |||||
Path.CheckSupportedPathFormat(path, true, true); | |||||
if (fileSystemEntryInfo == null) | |||||
if (fsEntryInfo == null) | |||||
{ | { | ||||
// MSDN: .NET 3.5+: DirectoryNotFoundException: | // MSDN: .NET 3.5+: DirectoryNotFoundException: | ||||
// Path does not exist or could not be found. | // Path does not exist or could not be found. | ||||
// Path refers to a file instead of a directory. | // Path refers to a file instead of a directory. | ||||
// The specified path is invalid (for example, it is on an unmapped drive). | // 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 | #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 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) | 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 | else | ||||
File.DeleteFileCore(transaction, fsei.LongFullPath, ignoreReadOnly, PathFormat.LongFullPath); | 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: | startRemoveDirectory: | ||||
if (!(transaction == null || !NativeMethods.IsAtLeastWindowsVista | |||||
var success = transaction == null || !NativeMethods.IsAtLeastWindowsVista | |||||
// RemoveDirectory() / RemoveDirectoryTransacted() | // RemoveDirectory() / RemoveDirectoryTransacted() | ||||
// In the ANSI version of this function, the name is limited to MAX_PATH characters. | // 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. | // RemoveDirectory on a symbolic link will remove the link itself. | ||||
? NativeMethods.RemoveDirectory(pathLp) | ? 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) | switch ((uint) lastError) | ||||
{ | { | ||||
case Win32Errors.ERROR_DIR_NOT_EMPTY: | 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: | case Win32Errors.ERROR_DIRECTORY: | ||||
@@ -361,18 +365,20 @@ namespace Alphaleonis.Win32.Filesystem | |||||
case Win32Errors.ERROR_PATH_NOT_FOUND: | case Win32Errors.ERROR_PATH_NOT_FOUND: | ||||
if (continueOnNotExist) | |||||
if (continueOnNotFound) | |||||
return; | return; | ||||
break; | break; | ||||
case Win32Errors.ERROR_SHARING_VIOLATION: | 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. | // 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); | NativeError.ThrowException(lastError, pathLp); | ||||
break; | break; | ||||
case Win32Errors.ERROR_ACCESS_DENIED: | case Win32Errors.ERROR_ACCESS_DENIED: | ||||
var data = new NativeMethods.WIN32_FILE_ATTRIBUTE_DATA(); | 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)) | if (data.dwFileAttributes != (FileAttributes) (-1)) | ||||
{ | { | ||||
@@ -383,7 +389,7 @@ namespace Alphaleonis.Win32.Filesystem | |||||
if (ignoreReadOnly) | if (ignoreReadOnly) | ||||
{ | { | ||||
// Reset directory attributes. | // Reset directory attributes. | ||||
File.SetAttributesCore(true, transaction, pathLp, FileAttributes.Normal, true, PathFormat.LongFullPath); | |||||
File.SetAttributesCore(true, transaction, pathLp, FileAttributes.Normal, PathFormat.LongFullPath); | |||||
goto startRemoveDirectory; | 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) | if (dataInitialised == Win32Errors.ERROR_SUCCESS) | ||||
// MSDN: .NET 3.5+: UnauthorizedAccessException: The caller does not have the required permission. | |||||
NativeError.ThrowException(lastError, pathLp); | NativeError.ThrowException(lastError, pathLp); | ||||
break; | break; | ||||
@@ -408,8 +415,6 @@ namespace Alphaleonis.Win32.Filesystem | |||||
NativeError.ThrowException(lastError, pathLp); | NativeError.ThrowException(lastError, pathLp); | ||||
} | } | ||||
#endregion // Remove | |||||
} | } | ||||
#endregion // Internal Methods | #endregion // Internal Methods | ||||
@@ -20,6 +20,7 @@ | |||||
*/ | */ | ||||
using System; | using System; | ||||
using System.Collections.Generic; | |||||
using System.Globalization; | using System.Globalization; | ||||
using System.IO; | using System.IO; | ||||
using System.Linq; | using System.Linq; | ||||
@@ -32,47 +33,76 @@ namespace Alphaleonis.Win32.Filesystem | |||||
/// <summary>[AlphaFS] Deletes empty subdirectories from the specified directory.</summary> | /// <summary>[AlphaFS] Deletes empty subdirectories from the specified directory.</summary> | ||||
/// <exception cref="ArgumentException"/> | /// <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> | |||||
[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="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="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="recursive"><see langword="true"/> deletes empty subdirectories from this directory and its subdirectories.</param> | ||||
[SecurityCritical] | [SecurityCritical] | ||||
public static void DeleteEmptySubdirectories(string path, bool recursive) | 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> | /// <summary>[AlphaFS] Deletes empty subdirectories from the specified directory.</summary> | ||||
/// <exception cref="ArgumentException"/> | /// <exception cref="ArgumentException"/> | ||||
/// <exception cref="ArgumentNullException"/> | /// <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="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="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> | /// <param name="pathFormat">Indicates the format of the path parameter(s).</param> | ||||
[SecurityCritical] | [SecurityCritical] | ||||
public static void DeleteEmptySubdirectories(string path, bool recursive, PathFormat pathFormat) | 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> | /// <summary>[AlphaFS] Deletes empty subdirectories from the specified directory.</summary> | ||||
/// <exception cref="ArgumentException"/> | /// <exception cref="ArgumentException"/> | ||||
/// <exception cref="ArgumentNullException"/> | /// <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="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="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="ignoreReadOnly"><see langword="true"/> overrides read only <see cref="FileAttributes"/> of empty directories.</param> | ||||
[SecurityCritical] | [SecurityCritical] | ||||
public static void DeleteEmptySubdirectories(string path, bool recursive, bool ignoreReadOnly) | 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> | /// <summary>[AlphaFS] Deletes empty subdirectories from the specified directory.</summary> | ||||
/// <exception cref="ArgumentException"/> | /// <exception cref="ArgumentException"/> | ||||
/// <exception cref="ArgumentNullException"/> | /// <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="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="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="ignoreReadOnly"><see langword="true"/> overrides read only <see cref="FileAttributes"/> of empty directories.</param> | ||||
@@ -80,28 +110,53 @@ namespace Alphaleonis.Win32.Filesystem | |||||
[SecurityCritical] | [SecurityCritical] | ||||
public static void DeleteEmptySubdirectories(string path, bool recursive, bool ignoreReadOnly, PathFormat pathFormat) | 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 | #region Transactional | ||||
/// <summary>[AlphaFS] Deletes empty subdirectories from the specified directory.</summary> | /// <summary>[AlphaFS] Deletes empty subdirectories from the specified directory.</summary> | ||||
/// <exception cref="ArgumentException"/> | /// <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> | |||||
[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="ArgumentNullException"/> | ||||
/// <exception cref="DirectoryNotFoundException"/> | |||||
/// <exception cref="IOException"/> | |||||
/// <exception cref="NotSupportedException"/> | |||||
/// <exception cref="UnauthorizedAccessException"/> | |||||
/// <exception cref="DirectoryReadOnlyException"/> | |||||
/// <param name="transaction">The transaction.</param> | /// <param name="transaction">The transaction.</param> | ||||
/// <param name="path">The name of the directory to remove empty subdirectories from.</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> | /// <param name="recursive"><see langword="true"/> deletes empty subdirectories from this directory and its subdirectories.</param> | ||||
[SecurityCritical] | [SecurityCritical] | ||||
public static void DeleteEmptySubdirectoriesTransacted(KernelTransaction transaction, string path, bool recursive) | 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> | /// <summary>[AlphaFS] Deletes empty subdirectories from the specified directory.</summary> | ||||
/// <exception cref="ArgumentException"/> | /// <exception cref="ArgumentException"/> | ||||
/// <exception cref="ArgumentNullException"/> | /// <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="transaction">The transaction.</param> | ||||
/// <param name="path">The name of the directory to remove empty subdirectories from.</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> | /// <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] | [SecurityCritical] | ||||
public static void DeleteEmptySubdirectoriesTransacted(KernelTransaction transaction, string path, bool recursive, PathFormat pathFormat) | 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> | /// <summary>[AlphaFS] Deletes empty subdirectories from the specified directory.</summary> | ||||
/// <exception cref="ArgumentException"/> | /// <exception cref="ArgumentException"/> | ||||
/// <exception cref="ArgumentNullException"/> | /// <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="transaction">The transaction.</param> | ||||
/// <param name="path">The name of the directory to remove empty subdirectories from.</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> | /// <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] | [SecurityCritical] | ||||
public static void DeleteEmptySubdirectoriesTransacted(KernelTransaction transaction, string path, bool recursive, bool ignoreReadOnly) | 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> | /// <summary>[AlphaFS] Deletes empty subdirectories from the specified directory.</summary> | ||||
/// <exception cref="ArgumentException"/> | /// <exception cref="ArgumentException"/> | ||||
/// <exception cref="ArgumentNullException"/> | /// <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="transaction">The transaction.</param> | ||||
/// <param name="path">The name of the directory to remove empty subdirectories from.</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> | /// <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] | [SecurityCritical] | ||||
public static void DeleteEmptySubdirectoriesTransacted(KernelTransaction transaction, string path, bool recursive, bool ignoreReadOnly, PathFormat pathFormat) | 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 | #endregion // Transactional | ||||
#region Internal Methods | #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="ArgumentException"/> | ||||
/// <exception cref="ArgumentNullException"/> | /// <exception cref="ArgumentNullException"/> | ||||
/// <exception cref="DirectoryNotFoundException"/> | /// <exception cref="DirectoryNotFoundException"/> | ||||
/// <exception cref="IOException"/> | /// <exception cref="IOException"/> | ||||
/// <exception cref="NotSupportedException"/> | /// <exception cref="NotSupportedException"/> | ||||
/// <exception cref="UnauthorizedAccessException"/> | /// <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="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="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="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="initialize">When <see langword="true"/> indicates the method is called externally.</param> | ||||
/// <param name="pathFormat">Indicates the format of the path parameter(s).</param> | /// <param name="pathFormat">Indicates the format of the path parameter(s).</param> | ||||
[SecurityCritical] | [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 | #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)) | if (!File.ExistsCore(true, transaction, path, pathFormat)) | ||||
NativeError.ThrowException(Win32Errors.ERROR_PATH_NOT_FOUND, path); | 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 | #endregion // Setup | ||||
// Ensure path is a directory. | // 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) | if (recursive) | ||||
dirEnumOptions |= DirectoryEnumerationOptions.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. | // Prevent deleting path itself. | ||||
if (!initialize) | 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; | ||||
using System.Diagnostics.CodeAnalysis; | |||||
using System.Security; | using System.Security; | ||||
using System.Security.AccessControl; | using System.Security.AccessControl; | ||||
@@ -54,6 +55,7 @@ namespace Alphaleonis.Win32.Filesystem | |||||
/// If the subdirectory already exists, this method does nothing. | /// If the subdirectory already exists, this method does nothing. | ||||
/// </remarks> | /// </remarks> | ||||
[SuppressMessage("Microsoft.Design", "CA1011:ConsiderPassingBaseTypesAsParameters")] | |||||
[SecurityCritical] | [SecurityCritical] | ||||
public DirectoryInfo CreateSubdirectory(string path, DirectorySecurity directorySecurity) | public DirectoryInfo CreateSubdirectory(string path, DirectorySecurity directorySecurity) | ||||
{ | { | ||||
@@ -108,6 +110,7 @@ namespace Alphaleonis.Win32.Filesystem | |||||
/// If the subdirectory already exists, this method does nothing. | /// If the subdirectory already exists, this method does nothing. | ||||
/// </remarks> | /// </remarks> | ||||
[SuppressMessage("Microsoft.Design", "CA1011:ConsiderPassingBaseTypesAsParameters")] | |||||
[SecurityCritical] | [SecurityCritical] | ||||
public DirectoryInfo CreateSubdirectory(string path, DirectorySecurity directorySecurity, bool compress) | 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. | /// If the subdirectory already exists, this method does nothing. | ||||
/// </remarks> | /// </remarks> | ||||
[SuppressMessage("Microsoft.Design", "CA1011:ConsiderPassingBaseTypesAsParameters")] | |||||
[SecurityCritical] | [SecurityCritical] | ||||
public DirectoryInfo CreateSubdirectory(string path, string templatePath, DirectorySecurity directorySecurity, bool compress) | 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="directorySecurity">The <see cref="DirectorySecurity"/> security to apply.</param> | ||||
/// <param name="compress">When <see langword="true"/> compresses the directory.</param> | /// <param name="compress">When <see langword="true"/> compresses the directory.</param> | ||||
[SecurityCritical] | [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 pathLp = Path.CombineCore(false, LongFullName, path); | ||||
string templatePathLp = templatePath == null ? null : | string templatePathLp = templatePath == null ? null : | ||||
@@ -39,7 +39,7 @@ namespace Alphaleonis.Win32.Filesystem | |||||
[SecurityCritical] | [SecurityCritical] | ||||
public override void Delete() | 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> | /// <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] | [SecurityCritical] | ||||
public void Delete(bool recursive) | 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 | #endregion // .NET | ||||
@@ -80,7 +80,7 @@ namespace Alphaleonis.Win32.Filesystem | |||||
[SecurityCritical] | [SecurityCritical] | ||||
public void Delete(bool recursive, bool ignoreReadOnly) | 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 | #endregion // AlphaFS | ||||
@@ -32,7 +32,7 @@ namespace Alphaleonis.Win32.Filesystem | |||||
[SecurityCritical] | [SecurityCritical] | ||||
public void DeleteEmptySubdirectories() | 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> | /// <summary>[AlphaFS] Deletes empty subdirectories from the <see cref="DirectoryInfo"/> instance.</summary> | ||||
@@ -40,7 +40,7 @@ namespace Alphaleonis.Win32.Filesystem | |||||
[SecurityCritical] | [SecurityCritical] | ||||
public void DeleteEmptySubdirectories(bool recursive) | 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> | /// <summary>[AlphaFS] Deletes empty subdirectories from the <see cref="DirectoryInfo"/> instance.</summary> | ||||
@@ -49,7 +49,7 @@ namespace Alphaleonis.Win32.Filesystem | |||||
[SecurityCritical] | [SecurityCritical] | ||||
public void DeleteEmptySubdirectories(bool recursive, bool ignoreReadOnly) | 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 | #endregion // AlphaFS | ||||
@@ -25,22 +25,22 @@ namespace Alphaleonis.Win32.Filesystem | |||||
public enum CopyMoveProgressResult | public enum CopyMoveProgressResult | ||||
{ | { | ||||
/// <summary>PROGRESS_CONTINUE | /// <summary>PROGRESS_CONTINUE | ||||
/// <para>Continue the copy operation.</para> | |||||
/// <para>Continue the copy/move operation.</para> | |||||
/// </summary> | /// </summary> | ||||
Continue = 0, | Continue = 0, | ||||
/// <summary>PROGRESS_CANCEL | /// <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> | /// </summary> | ||||
Cancel = 1, | Cancel = 1, | ||||
/// <summary>PROGRESS_STOP | /// <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> | /// </summary> | ||||
Stop = 2, | Stop = 2, | ||||
/// <summary>PROGRESS_QUIET | /// <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> | /// </summary> | ||||
Quiet = 3 | 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. | /// This flag must be set in the Flags parameter if the Enumerator parameter specifies a Device Instance ID. | ||||
/// </para> | /// </para> | ||||
/// </summary> | /// </summary> | ||||
DeviceInterface = 16, | |||||
DeviceInterface = 16 | |||||
} | } | ||||
} | } | ||||
} | } |
@@ -55,6 +55,6 @@ namespace Alphaleonis.Win32.Filesystem | |||||
/// <para>Do not broadcast the WM_SETTINGCHANGE message.</para> | /// <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> | /// <para>By default, this message is broadcast to notify the shell and applications of the change.</para> | ||||
/// </summary> | /// </summary> | ||||
NoBroadcastSystem = 8, | |||||
NoBroadcastSystem = 8 | |||||
} | } | ||||
} | } |
@@ -26,7 +26,7 @@ using System.IO; | |||||
namespace Alphaleonis.Win32.Filesystem | namespace Alphaleonis.Win32.Filesystem | ||||
{ | { | ||||
/// <summary>Specifies how the operating system should open a file.</summary> | /// <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] | [Flags] | ||||
public enum ExtendedFileAttributes | public enum ExtendedFileAttributes | ||||
{ | { | ||||
@@ -138,7 +138,7 @@ namespace Alphaleonis.Win32.Filesystem | |||||
/// <para>will resume the enumeration operation after the last file is returned.</para> | /// <para>will resume the enumeration operation after the last file is returned.</para> | ||||
/// </remarks> | /// </remarks> | ||||
/// </summary> | /// </summary> | ||||
FileIdBothDirectoryInfo = 10, | |||||
FileIdBothDirectoryInfo = 10 | |||||
#endregion // FILE_ID_BOTH_DIR_INFO | #endregion // FILE_ID_BOTH_DIR_INFO | ||||
@@ -28,6 +28,6 @@ namespace Alphaleonis.Win32.Filesystem | |||||
Absolute = 0, | Absolute = 0, | ||||
/// <summary>The symbolic link is relative.</summary> | /// <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> | /// <summary>Initializes a new instance of the <see cref="TransactionException"/> class.</summary> | ||||
/// <param name="message">The message.</param> | /// <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> | /// <summary>Initializes a new instance of the <see cref="TransactionException"/> class.</summary> | ||||
/// <param name="message">The message.</param> | /// <param name="message">The message.</param> | ||||
/// <param name="innerException">The inner exception.</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> | /// <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="info">The data for serializing or deserializing the object.</param> | ||||
/// <param name="context">The source and destination for 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="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> | /// <param name="userProgressData">The argument to be passed to the callback function. This parameter can be <see langword="null"/>.</param> | ||||
[SecurityCritical] | [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, | /// <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="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> | /// <param name="pathFormat">Indicates the format of the path parameter(s).</param> | ||||
[SecurityCritical] | [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="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> | /// <param name="userProgressData">The argument to be passed to the callback function. This parameter can be <see langword="null"/>.</param> | ||||
[SecurityCritical] | [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, | /// <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="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> | /// <param name="pathFormat">Indicates the format of the path parameter(s).</param> | ||||
[SecurityCritical] | [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 | #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="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> | /// <param name="userProgressData">The argument to be passed to the callback function. This parameter can be <see langword="null"/>.</param> | ||||
[SecurityCritical] | [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, | /// <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="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> | /// <param name="pathFormat">Indicates the format of the path parameter(s).</param> | ||||
[SecurityCritical] | [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="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> | /// <param name="userProgressData">The argument to be passed to the callback function. This parameter can be <see langword="null"/>.</param> | ||||
[SecurityCritical] | [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, | /// <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="NotSupportedException"/> | ||||
/// <exception cref="UnauthorizedAccessException"/> | /// <exception cref="UnauthorizedAccessException"/> | ||||
[SecurityCritical] | [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 | #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="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> | /// <param name="userProgressData">The argument to be passed to the callback function. This parameter can be <see langword="null"/>.</param> | ||||
[SecurityCritical] | [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> | /// <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="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> | /// <param name="pathFormat">Indicates the format of the path parameter(s).</param> | ||||
[SecurityCritical] | [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 | #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="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> | /// <param name="userProgressData">The argument to be passed to the callback function. This parameter can be <see langword="null"/>.</param> | ||||
[SecurityCritical] | [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> | /// <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="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> | /// <param name="pathFormat">Indicates the format of the path parameter(s).</param> | ||||
[SecurityCritical] | [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 | #endregion // Transactional | ||||
@@ -1087,10 +1087,8 @@ namespace Alphaleonis.Win32.Filesystem | |||||
var sourceFileNameLp = sourceFileName; | var sourceFileNameLp = sourceFileName; | ||||
var destFileNameLp = destinationFileName; | var destFileNameLp = destinationFileName; | ||||
var skipPathChecks = pathFormat == PathFormat.LongFullPath; | |||||
if (!skipPathChecks) | |||||
if (pathFormat != PathFormat.LongFullPath) | |||||
{ | { | ||||
Path.CheckSupportedPathFormat(sourceFileName, true, true); | Path.CheckSupportedPathFormat(sourceFileName, true, true); | ||||
Path.CheckSupportedPathFormat(destinationFileName, true, true); | Path.CheckSupportedPathFormat(destinationFileName, true, true); | ||||
@@ -1098,30 +1096,27 @@ namespace Alphaleonis.Win32.Filesystem | |||||
sourceFileNameLp = Path.GetExtendedLengthPathCore(transaction, sourceFileName, pathFormat, GetFullPathOptions.RemoveTrailingDirectorySeparator); | sourceFileNameLp = Path.GetExtendedLengthPathCore(transaction, sourceFileName, pathFormat, GetFullPathOptions.RemoveTrailingDirectorySeparator); | ||||
destFileNameLp = Path.GetExtendedLengthPathCore(transaction, destinationFileName, 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. | // Determine Copy or Move action. | ||||
var isCopy = DetermineIsCopy(copyOptions, moveOptions); | var isCopy = DetermineIsCopy(copyOptions, moveOptions); | ||||
var isMove = !isCopy; | 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. | // Setup callback function for progress notifications. | ||||
var routine = progressHandler != null | |||||
var routine = !raiseException | |||||
? (totalFileSize, totalBytesTransferred, streamSize, streamBytesTransferred, dwStreamNumber, dwCallbackReason, hSourceFile, hDestinationFile, lpData) => | ? (totalFileSize, totalBytesTransferred, streamSize, streamBytesTransferred, dwStreamNumber, dwCallbackReason, hSourceFile, hDestinationFile, lpData) => | ||||
progressHandler(totalFileSize, totalBytesTransferred, streamSize, streamBytesTransferred, dwStreamNumber, dwCallbackReason, userProgressData) | progressHandler(totalFileSize, totalBytesTransferred, streamSize, streamBytesTransferred, dwStreamNumber, dwCallbackReason, userProgressData) | ||||
: (NativeMethods.NativeCopyMoveProgressRoutine) null; | : (NativeMethods.NativeCopyMoveProgressRoutine) null; | ||||
var cmr = copyMoveResult ?? new CopyMoveResult(sourceFileNameLp, destFileNameLp, false, (int) Win32Errors.ERROR_SUCCESS); | |||||
#endregion // Setup | #endregion // Setup | ||||
@@ -1153,8 +1148,6 @@ namespace Alphaleonis.Win32.Filesystem | |||||
: isMove | : isMove | ||||
? NativeMethods.MoveFileTransacted(sourceFileNameLp, destFileNameLp, routine, IntPtr.Zero, (MoveOptions) moveOptions, transaction.SafeHandle) | ? NativeMethods.MoveFileTransacted(sourceFileNameLp, destFileNameLp, routine, IntPtr.Zero, (MoveOptions) moveOptions, transaction.SafeHandle) | ||||
: NativeMethods.CopyFileTransacted(sourceFileNameLp, destFileNameLp, routine, IntPtr.Zero, out cancel, (CopyOptions) copyOptions, transaction.SafeHandle); | : NativeMethods.CopyFileTransacted(sourceFileNameLp, destFileNameLp, routine, IntPtr.Zero, out cancel, (CopyOptions) copyOptions, transaction.SafeHandle); | ||||
var lastError = (uint) Marshal.GetLastWin32Error(); | var lastError = (uint) Marshal.GetLastWin32Error(); | ||||
@@ -1174,8 +1167,7 @@ namespace Alphaleonis.Win32.Filesystem | |||||
// CopyFileEx will return zero and GetLastError will return ERROR_REQUEST_ABORTED. | // CopyFileEx will return zero and GetLastError will return ERROR_REQUEST_ABORTED. | ||||
// In this case, the partially copied destination file is left intact. | // In this case, the partially copied destination file is left intact. | ||||
cancel = true; | |||||
cmr.IsCanceled = cancel; | |||||
cmr.IsCanceled = true; | |||||
} | } | ||||
else if (raiseException) | else if (raiseException) | ||||
@@ -1267,7 +1259,7 @@ namespace Alphaleonis.Win32.Filesystem | |||||
if (((MoveOptions) moveOptions & MoveOptions.ReplaceExisting) != 0) | if (((MoveOptions) moveOptions & MoveOptions.ReplaceExisting) != 0) | ||||
{ | { | ||||
// Reset file system object attributes. | // Reset file system object attributes. | ||||
SetAttributesCore(isFolder, transaction, destFileNameLp, FileAttributes.Normal, true, PathFormat.LongFullPath); | |||||
SetAttributesCore(isFolder, transaction, destFileNameLp, FileAttributes.Normal, PathFormat.LongFullPath); | |||||
goto startCopyMove; | goto startCopyMove; | ||||
} | } | ||||
@@ -96,7 +96,7 @@ namespace Alphaleonis.Win32.Filesystem | |||||
[SecurityCritical] | [SecurityCritical] | ||||
internal static void CreateHardlinkCore(KernelTransaction transaction, string fileName, string existingFileName, PathFormat pathFormat) | 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 fileNameLp = Path.GetExtendedLengthPathCore(transaction, fileName, pathFormat, options); | ||||
string existingFileNameLp = Path.GetExtendedLengthPathCore(transaction, existingFileName, pathFormat, options); | string existingFileNameLp = Path.GetExtendedLengthPathCore(transaction, existingFileName, pathFormat, options); | ||||
@@ -110,7 +110,7 @@ namespace Alphaleonis.Win32.Filesystem | |||||
if (!NativeMethods.IsAtLeastWindowsVista) | if (!NativeMethods.IsAtLeastWindowsVista) | ||||
throw new PlatformNotSupportedException(Resources.Requires_Windows_Vista_Or_Higher); | 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 symlinkFileNameLp = Path.GetExtendedLengthPathCore(transaction, symlinkFileName, pathFormat, options); | ||||
string targetFileNameRp = Path.GetExtendedLengthPathCore(transaction, targetFileName, pathFormat, options); | string targetFileNameRp = Path.GetExtendedLengthPathCore(transaction, targetFileName, pathFormat, options); | ||||
@@ -209,7 +209,7 @@ namespace Alphaleonis.Win32.Filesystem | |||||
if (ignoreReadOnly) | if (ignoreReadOnly) | ||||
{ | { | ||||
// Reset file attributes. | // Reset file attributes. | ||||
SetAttributesCore(false, transaction, pathLp, FileAttributes.Normal, true, PathFormat.LongFullPath); | |||||
SetAttributesCore(false, transaction, pathLp, FileAttributes.Normal, PathFormat.LongFullPath); | |||||
goto startDeleteFile; | goto startDeleteFile; | ||||
} | } | ||||
@@ -85,7 +85,7 @@ namespace Alphaleonis.Win32.Filesystem | |||||
// Reset file/directory attributes. | // Reset file/directory attributes. | ||||
// MSDN: If lpFileName specifies a read-only file, the function fails and GetLastError returns ERROR_FILE_READ_ONLY. | // 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() | // EncryptFile() / DecryptFile() | ||||
// In the ANSI version of this function, the name is limited to 248 characters. | // In the ANSI version of this function, the name is limited to 248 characters. | ||||
@@ -83,7 +83,7 @@ namespace Alphaleonis.Win32.Filesystem | |||||
[SecurityCritical] | [SecurityCritical] | ||||
internal static string GetHashCore(KernelTransaction transaction, string fileFullPath, HashType hashType, PathFormat pathFormat) | 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); | var fileNameLp = Path.GetExtendedLengthPathCore(transaction, fileFullPath, pathFormat, options); | ||||
byte[] hash = null; | byte[] hash = null; | ||||
@@ -151,7 +151,7 @@ namespace Alphaleonis.Win32.Filesystem | |||||
[SecurityCritical] | [SecurityCritical] | ||||
internal static void ReplaceCore(string sourceFileName, string destinationFileName, string destinationBackupFileName, bool ignoreMetadataErrors, PathFormat pathFormat) | 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 sourceFileNameLp = Path.GetExtendedLengthPathCore(null, sourceFileName, pathFormat, options); | ||||
string destinationFileNameLp = Path.GetExtendedLengthPathCore(null, destinationFileName, pathFormat, options); | string destinationFileNameLp = Path.GetExtendedLengthPathCore(null, destinationFileName, pathFormat, options); | ||||
@@ -44,7 +44,7 @@ namespace Alphaleonis.Win32.Filesystem | |||||
[SecurityCritical] | [SecurityCritical] | ||||
public static void SetAttributes(string path, FileAttributes fileAttributes) | 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> | /// <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] | [SecurityCritical] | ||||
public static void SetAttributes(string path, FileAttributes fileAttributes, PathFormat pathFormat) | 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] | [SecurityCritical] | ||||
public static void SetAttributesTransacted(KernelTransaction transaction, string path, FileAttributes fileAttributes) | 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> | /// <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] | [SecurityCritical] | ||||
public static void SetAttributesTransacted(KernelTransaction transaction, string path, FileAttributes fileAttributes, PathFormat pathFormat) | 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 | #endregion // Transacted | ||||
@@ -123,16 +123,13 @@ namespace Alphaleonis.Win32.Filesystem | |||||
/// <param name="fileAttributes"> | /// <param name="fileAttributes"> | ||||
/// The attributes to set for the file or directory. Note that all other values override <see cref="FileAttributes.Normal"/>. | /// The attributes to set for the file or directory. Note that all other values override <see cref="FileAttributes.Normal"/>. | ||||
/// </param> | /// </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> | /// <param name="pathFormat">Indicates the format of the path parameter(s).</param> | ||||
[SecurityCritical] | [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() | // SetFileAttributes() | ||||
// In the ANSI version of this function, the name is limited to MAX_PATH characters. | // 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. | // 2013-01-13: MSDN confirms LongPath usage. | ||||
? NativeMethods.SetFileAttributes(pathLp, fileAttributes) | ? 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) | switch (lastError) | ||||
{ | { | ||||
// MSDN: .NET 3.5+: ArgumentException: FileSystemInfo().Attributes | // MSDN: .NET 3.5+: ArgumentException: FileSystemInfo().Attributes | ||||
@@ -155,7 +151,7 @@ namespace Alphaleonis.Win32.Filesystem | |||||
case Win32Errors.ERROR_FILE_NOT_FOUND: | case Win32Errors.ERROR_FILE_NOT_FOUND: | ||||
if (isFolder) | 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+: DirectoryNotFoundException: The specified path is invalid, (for example, it is on an unmapped drive). | ||||
// MSDN: .NET 3.5+: FileNotFoundException: The file cannot be found. | // MSDN: .NET 3.5+: FileNotFoundException: The file cannot be found. | ||||
@@ -78,7 +78,7 @@ namespace Alphaleonis.Win32.Filesystem | |||||
[SecurityCritical] | [SecurityCritical] | ||||
public FileInfo Replace(string destinationFileName, string destinationBackupFileName, PathFormat pathFormat) | 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 destinationFileNameLp = Path.GetExtendedLengthPathCore(Transaction, destinationFileName, pathFormat, options); | ||||
string destinationBackupFileNameLp = destinationBackupFileName != null | string destinationBackupFileNameLp = destinationBackupFileName != null | ||||
@@ -105,7 +105,7 @@ namespace Alphaleonis.Win32.Filesystem | |||||
[SecurityCritical] | [SecurityCritical] | ||||
public FileInfo Replace(string destinationFileName, string destinationBackupFileName, bool ignoreMetadataErrors, PathFormat pathFormat) | 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 destinationFileNameLp = Path.GetExtendedLengthPathCore(Transaction, destinationFileName, pathFormat, options); | ||||
string destinationBackupFileNameLp = destinationBackupFileName != null | string destinationBackupFileNameLp = destinationBackupFileName != null | ||||
@@ -266,7 +266,7 @@ namespace Alphaleonis.Win32.Filesystem | |||||
[SecurityCritical] | [SecurityCritical] | ||||
set | set | ||||
{ | { | ||||
File.SetAttributesCore(IsDirectory, Transaction, LongFullName, value, false, PathFormat.LongFullPath); | |||||
File.SetAttributesCore(IsDirectory, Transaction, LongFullName, value, PathFormat.LongFullPath); | |||||
Reset(); | Reset(); | ||||
} | } | ||||
} | } | ||||
@@ -547,7 +547,7 @@ namespace Alphaleonis.Win32.Filesystem | |||||
#region DisplayPath | #region DisplayPath | ||||
/// <summary>Returns the path as a string.</summary> | /// <summary>Returns the path as a string.</summary> | ||||
protected internal string DisplayPath { get; set; } | |||||
protected internal string DisplayPath { get; protected set; } | |||||
#endregion // DisplayPath | #endregion // DisplayPath | ||||
@@ -590,7 +590,7 @@ namespace Alphaleonis.Win32.Filesystem | |||||
#region IsDirectory | #region IsDirectory | ||||
/// <summary>[AlphaFS] The initial "IsDirectory" indicator that was passed to the constructor.</summary> | /// <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 | #endregion // IsDirectory | ||||
@@ -604,7 +604,7 @@ namespace Alphaleonis.Win32.Filesystem | |||||
#region Transaction | #region Transaction | ||||
/// <summary>[AlphaFS] Represents the KernelTransaction that was passed to the constructor.</summary> | /// <summary>[AlphaFS] Represents the KernelTransaction that was passed to the constructor.</summary> | ||||
public KernelTransaction Transaction { get; set; } | |||||
protected KernelTransaction Transaction { get; set; } | |||||
#endregion // Transaction | #endregion // Transaction | ||||
@@ -53,7 +53,7 @@ namespace Alphaleonis.Win32.Filesystem | |||||
[SuppressMessage("Microsoft.Security", "CA5122:PInvokesShouldNotBeSafeCriticalFxCopRule")] | [SuppressMessage("Microsoft.Security", "CA5122:PInvokesShouldNotBeSafeCriticalFxCopRule")] | ||||
[DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Unicode, EntryPoint = "DeleteVolumeMountPointW"), SuppressUnmanagedCodeSecurity] | [DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Unicode, EntryPoint = "DeleteVolumeMountPointW"), SuppressUnmanagedCodeSecurity] | ||||
[return: MarshalAs(UnmanagedType.Bool)] | [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> | /// <summary>Retrieves the name of a volume on a computer. FindFirstVolume is used to begin scanning the volumes of a computer.</summary> | ||||
/// <returns> | /// <returns> | ||||
@@ -64,7 +64,7 @@ namespace Alphaleonis.Win32.Filesystem | |||||
/// <remarks>Minimum supported server: Windows Server 2003 [desktop apps only]</remarks> | /// <remarks>Minimum supported server: Windows Server 2003 [desktop apps only]</remarks> | ||||
[SuppressMessage("Microsoft.Security", "CA5122:PInvokesShouldNotBeSafeCriticalFxCopRule")] | [SuppressMessage("Microsoft.Security", "CA5122:PInvokesShouldNotBeSafeCriticalFxCopRule")] | ||||
[DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Unicode, EntryPoint = "FindFirstVolumeW"), SuppressUnmanagedCodeSecurity] | [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> | /// <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> | /// <returns> | ||||
@@ -75,7 +75,7 @@ namespace Alphaleonis.Win32.Filesystem | |||||
/// <remarks>Minimum supported server: Windows Server 2003 [desktop apps only]</remarks> | /// <remarks>Minimum supported server: Windows Server 2003 [desktop apps only]</remarks> | ||||
[SuppressMessage("Microsoft.Security", "CA5122:PInvokesShouldNotBeSafeCriticalFxCopRule")] | [SuppressMessage("Microsoft.Security", "CA5122:PInvokesShouldNotBeSafeCriticalFxCopRule")] | ||||
[DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Unicode, EntryPoint = "FindFirstVolumeMountPointW"), SuppressUnmanagedCodeSecurity] | [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> | /// <summary>Continues a volume search started by a call to the FindFirstVolume function. FindNextVolume finds one volume per call.</summary> | ||||
/// <returns> | /// <returns> | ||||
@@ -87,7 +87,7 @@ namespace Alphaleonis.Win32.Filesystem | |||||
[SuppressMessage("Microsoft.Security", "CA5122:PInvokesShouldNotBeSafeCriticalFxCopRule")] | [SuppressMessage("Microsoft.Security", "CA5122:PInvokesShouldNotBeSafeCriticalFxCopRule")] | ||||
[DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Unicode, EntryPoint = "FindNextVolumeW"), SuppressUnmanagedCodeSecurity] | [DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Unicode, EntryPoint = "FindNextVolumeW"), SuppressUnmanagedCodeSecurity] | ||||
[return: MarshalAs(UnmanagedType.Bool)] | [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> | /// <summary>Continues a mounted folder search started by a call to the FindFirstVolumeMountPoint function. FindNextVolumeMountPoint finds one mounted folder per call.</summary> | ||||
/// <returns> | /// <returns> | ||||
@@ -100,7 +100,7 @@ namespace Alphaleonis.Win32.Filesystem | |||||
[SuppressMessage("Microsoft.Security", "CA5122:PInvokesShouldNotBeSafeCriticalFxCopRule")] | [SuppressMessage("Microsoft.Security", "CA5122:PInvokesShouldNotBeSafeCriticalFxCopRule")] | ||||
[DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Unicode, EntryPoint = "FindNextVolumeMountPointW"), SuppressUnmanagedCodeSecurity] | [DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Unicode, EntryPoint = "FindNextVolumeMountPointW"), SuppressUnmanagedCodeSecurity] | ||||
[return: MarshalAs(UnmanagedType.Bool)] | [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> | /// <summary>Closes the specified volume search handle.</summary> | ||||
/// <remarks> | /// <remarks> | ||||
@@ -114,7 +114,7 @@ namespace Alphaleonis.Win32.Filesystem | |||||
[SuppressMessage("Microsoft.Security", "CA5122:PInvokesShouldNotBeSafeCriticalFxCopRule")] | [SuppressMessage("Microsoft.Security", "CA5122:PInvokesShouldNotBeSafeCriticalFxCopRule")] | ||||
[DllImport("kernel32.dll", SetLastError = false, CharSet = CharSet.Unicode), SuppressUnmanagedCodeSecurity] | [DllImport("kernel32.dll", SetLastError = false, CharSet = CharSet.Unicode), SuppressUnmanagedCodeSecurity] | ||||
[return: MarshalAs(UnmanagedType.Bool)] | [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> | /// <summary>Closes the specified mounted folder search handle.</summary> | ||||
/// <remarks> | /// <remarks> | ||||
@@ -129,7 +129,7 @@ namespace Alphaleonis.Win32.Filesystem | |||||
[SuppressMessage("Microsoft.Security", "CA5122:PInvokesShouldNotBeSafeCriticalFxCopRule")] | [SuppressMessage("Microsoft.Security", "CA5122:PInvokesShouldNotBeSafeCriticalFxCopRule")] | ||||
[DllImport("kernel32.dll", SetLastError = false, CharSet = CharSet.Unicode), SuppressUnmanagedCodeSecurity] | [DllImport("kernel32.dll", SetLastError = false, CharSet = CharSet.Unicode), SuppressUnmanagedCodeSecurity] | ||||
[return: MarshalAs(UnmanagedType.Bool)] | [return: MarshalAs(UnmanagedType.Bool)] | ||||
internal extern static bool FindVolumeMountPointClose(IntPtr hFindVolume); | |||||
internal static extern bool FindVolumeMountPointClose(IntPtr hFindVolume); | |||||
/// <summary> | /// <summary> | ||||
/// Determines whether a disk drive is a removable, fixed, CD-ROM, RAM disk, or network drive. | /// 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")] | [SuppressMessage("Microsoft.Security", "CA5122:PInvokesShouldNotBeSafeCriticalFxCopRule")] | ||||
[DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Unicode, EntryPoint = "GetDriveTypeW"), SuppressUnmanagedCodeSecurity] | [DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Unicode, EntryPoint = "GetDriveTypeW"), SuppressUnmanagedCodeSecurity] | ||||
[return: MarshalAs(UnmanagedType.U4)] | [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> | /// <summary> | ||||
/// Retrieves a bitmask representing the currently available disk drives. | /// Retrieves a bitmask representing the currently available disk drives. | ||||
@@ -180,7 +180,7 @@ namespace Alphaleonis.Win32.Filesystem | |||||
[SuppressMessage("Microsoft.Security", "CA5122:PInvokesShouldNotBeSafeCriticalFxCopRule")] | [SuppressMessage("Microsoft.Security", "CA5122:PInvokesShouldNotBeSafeCriticalFxCopRule")] | ||||
[DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Unicode, EntryPoint = "GetVolumeInformationW"), SuppressUnmanagedCodeSecurity] | [DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Unicode, EntryPoint = "GetVolumeInformationW"), SuppressUnmanagedCodeSecurity] | ||||
[return: MarshalAs(UnmanagedType.Bool)] | [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> | /// <summary>Retrieves information about the file system and volume associated with the specified file.</summary> | ||||
/// <returns> | /// <returns> | ||||
@@ -194,7 +194,7 @@ namespace Alphaleonis.Win32.Filesystem | |||||
[SuppressMessage("Microsoft.Security", "CA5122:PInvokesShouldNotBeSafeCriticalFxCopRule")] | [SuppressMessage("Microsoft.Security", "CA5122:PInvokesShouldNotBeSafeCriticalFxCopRule")] | ||||
[DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Unicode, EntryPoint = "GetVolumeInformationByHandleW"), SuppressUnmanagedCodeSecurity] | [DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Unicode, EntryPoint = "GetVolumeInformationByHandleW"), SuppressUnmanagedCodeSecurity] | ||||
[return: MarshalAs(UnmanagedType.Bool)] | [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> | /// <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> | /// <returns> | ||||
@@ -255,7 +255,7 @@ namespace Alphaleonis.Win32.Filesystem | |||||
[SuppressMessage("Microsoft.Security", "CA5122:PInvokesShouldNotBeSafeCriticalFxCopRule")] | [SuppressMessage("Microsoft.Security", "CA5122:PInvokesShouldNotBeSafeCriticalFxCopRule")] | ||||
[DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Unicode, EntryPoint = "SetVolumeLabelW"), SuppressUnmanagedCodeSecurity] | [DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Unicode, EntryPoint = "SetVolumeLabelW"), SuppressUnmanagedCodeSecurity] | ||||
[return: MarshalAs(UnmanagedType.Bool)] | [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> | /// <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> | /// <remarks>Minimum supported client: Windows XP [desktop apps only].</remarks> | ||||
@@ -267,7 +267,7 @@ namespace Alphaleonis.Win32.Filesystem | |||||
[SuppressMessage("Microsoft.Security", "CA5122:PInvokesShouldNotBeSafeCriticalFxCopRule")] | [SuppressMessage("Microsoft.Security", "CA5122:PInvokesShouldNotBeSafeCriticalFxCopRule")] | ||||
[DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Unicode, EntryPoint = "SetVolumeMountPointW"), SuppressUnmanagedCodeSecurity] | [DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Unicode, EntryPoint = "SetVolumeMountPointW"), SuppressUnmanagedCodeSecurity] | ||||
[return: MarshalAs(UnmanagedType.Bool)] | [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> | /// <summary>Retrieves information about MS-DOS device names.</summary> | ||||
/// <remarks>Minimum supported client: Windows XP [desktop apps only].</remarks> | /// <remarks>Minimum supported client: Windows XP [desktop apps only].</remarks> | ||||
@@ -67,7 +67,7 @@ namespace Alphaleonis.Win32.Filesystem | |||||
if (obj == null || GetType() != obj.GetType()) | if (obj == null || GetType() != obj.GetType()) | ||||
return false; | return false; | ||||
FILETIME other = obj is FILETIME ? (FILETIME)obj : new FILETIME(); | |||||
FILETIME other = obj as FILETIME? ?? new FILETIME(); | |||||
return (other.dwHighDateTime.Equals(dwHighDateTime) && | return (other.dwHighDateTime.Equals(dwHighDateTime) && | ||||
other.dwLowDateTime.Equals(dwLowDateTime)); | other.dwLowDateTime.Equals(dwLowDateTime)); | ||||
@@ -63,7 +63,7 @@ namespace Alphaleonis.Win32.Filesystem | |||||
public static readonly string StreamSeparator = StreamSeparatorChar.ToString(CultureInfo.CurrentCulture); | public static readonly string StreamSeparator = StreamSeparatorChar.ToString(CultureInfo.CurrentCulture); | ||||
/// <summary>[AlphaFS] StreamDataLabel = ':$DATA' Provides a platform-specific Stream :$DATA label.</summary> | /// <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> | /// <summary>[AlphaFS] StringTerminatorChar = '\0' String Terminator Suffix.</summary> | ||||
public const char StringTerminatorChar = '\0'; | public const char StringTerminatorChar = '\0'; | ||||
@@ -357,10 +357,9 @@ namespace Alphaleonis.Win32.Filesystem | |||||
if (path.StartsWith(LongPathPrefix, StringComparison.OrdinalIgnoreCase)) | if (path.StartsWith(LongPathPrefix, StringComparison.OrdinalIgnoreCase)) | ||||
return GetLongPathCore(path.Substring(0, rootLengthPath), GetFullPathOptions.None); | 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 | #endregion // GetPathRoot | ||||
@@ -656,15 +656,12 @@ namespace Alphaleonis.Win32.Filesystem | |||||
[SecurityCritical] | [SecurityCritical] | ||||
public static bool PathFileExists(string path) | public static bool PathFileExists(string path) | ||||
{ | { | ||||
if (Utils.IsNullOrWhiteSpace(path)) | |||||
return false; | |||||
// PathFileExists() | // PathFileExists() | ||||
// In the ANSI version of this function, the name is limited to 248 characters. | // 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. | // 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. | // 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. | // The deviceName cannot have a trailing backslash. | ||||
deviceName = Path.RemoveTrailingDirectorySeparator(deviceName, false); | deviceName = Path.RemoveTrailingDirectorySeparator(deviceName, false); | ||||
var searchFilter = (deviceName != null); | |||||
var searchFilter = deviceName != null; | |||||
// Only process options if a device is supplied. | // Only process options if a device is supplied. | ||||
if (searchFilter) | if (searchFilter) | ||||
@@ -49,7 +49,7 @@ namespace Alphaleonis.Win32.Network | |||||
/// <summary>RESOURCETYPE_PRINT | /// <summary>RESOURCETYPE_PRINT | ||||
/// <para>All print resources.</para> | /// <para>All print resources.</para> | ||||
/// </summary> | /// </summary> | ||||
Print = 2, | |||||
Print = 2 | |||||
} | } | ||||
} | } | ||||
} | } |
@@ -41,6 +41,6 @@ namespace Alphaleonis.Win32.Network | |||||
Info503 = 503, | Info503 = 503, | ||||
/// <summary>Contains information about the shared resource.</summary> | /// <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> | /// <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", "CA1709:IdentifiersShouldBeCasedCorrectly", MessageId = "Ca")] | ||||
[SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Ca")] | [SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Ca")] | ||||
EnableCa = 16384, | |||||
EnableCa = 16384 | |||||
} | } | ||||
} | } |
@@ -199,7 +199,7 @@ namespace Alphaleonis.Win32.Network | |||||
totalEntries = 0; | totalEntries = 0; | ||||
// When host == null, the local computer is used. | // 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. | // So, explicitly state Environment.MachineName to prevent this. | ||||
// Furthermore, the UNC prefix: \\ is not required and always removed. | // 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); | 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; | totalEntries = 0; | ||||
// When host == null, the local computer is used. | // 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. | // So, explicitly state Environment.MachineName to prevent this. | ||||
// Furthermore, the UNC prefix: \\ is not required and always removed. | // 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); | 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) => | (FunctionData functionData, out SafeGlobalMemoryBufferHandle buffer, int prefMaxLen, out uint entriesRead, out uint totalEntries, out uint resume) => | ||||
{ | { | ||||
// When host == null, the local computer is used. | // 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. | // So, explicitly state Environment.MachineName to prevent this. | ||||
// Furthermore, the UNC prefix: \\ is not required and always removed. | // 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); | 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); | 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) => | (FunctionData functionData, out SafeGlobalMemoryBufferHandle buffer, int prefMaxLen, out uint entriesRead, out uint totalEntries, out uint resumeHandle) => | ||||
{ | { | ||||
// When host == null, the local computer is used. | // 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. | // So, explicitly state Environment.MachineName to prevent this. | ||||
// Furthermore, the UNC prefix: \\ is not required and always removed. | // 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); | 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] | [SecurityCritical] | ||||
public static ShareInfo GetShareInfo(string uncPath, bool continueOnException) | 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); | return GetShareInfoCore(ShareInfoLevel.Info503, unc[0], unc[1], continueOnException); | ||||
} | } | ||||
@@ -180,7 +180,7 @@ namespace Alphaleonis.Win32.Network | |||||
[SecurityCritical] | [SecurityCritical] | ||||
public static ShareInfo GetShareInfo(ShareInfoLevel shareLevel, string uncPath, bool continueOnException) | 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); | return GetShareInfoCore(shareLevel, unc[0], unc[1], continueOnException); | ||||
} | } | ||||
@@ -213,7 +213,7 @@ namespace Alphaleonis.Win32.Network | |||||
#region EnumerateOpenConnectionsCore | #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> | /// <returns><see cref="OpenConnectionInfo"/> connection information from the specified <paramref name="host"/>.</returns> | ||||
/// <exception cref="ArgumentNullException"/> | /// <exception cref="ArgumentNullException"/> | ||||
/// <exception cref="NetworkInformationException"/> | /// <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); | return NativeMethods.NetConnectionEnum(stripUnc, functionData.ExtraData1, 1, out buffer, NativeMethods.MaxPreferredLength, out entriesRead, out totalEntries, out resumeHandle); | ||||
}, | }, | ||||
continueOnException); | continueOnException); | ||||
} | } | ||||
@@ -260,16 +261,14 @@ namespace Alphaleonis.Win32.Network | |||||
internal static IEnumerable<ShareInfo> EnumerateSharesCore(string host, ShareType shareType, bool continueOnException) | internal static IEnumerable<ShareInfo> EnumerateSharesCore(string host, ShareType shareType, bool continueOnException) | ||||
{ | { | ||||
// When host == null, the local computer is used. | // 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. | // So, explicitly state Environment.MachineName to prevent this. | ||||
// Furthermore, the UNC prefix: \\ is not required and always removed. | // 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(); | 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. | // Try SHARE_INFO_503 structure. | ||||
foreach (var si in EnumerateNetworkObjectCore(fd, (NativeMethods.SHARE_INFO_503 structure, SafeGlobalMemoryBufferHandle buffer) => | foreach (var si in EnumerateNetworkObjectCore(fd, (NativeMethods.SHARE_INFO_503 structure, SafeGlobalMemoryBufferHandle buffer) => | ||||
@@ -323,14 +322,12 @@ namespace Alphaleonis.Win32.Network | |||||
return null; | return null; | ||||
// When host == null, the local computer is used. | // 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. | // So, explicitly state Environment.MachineName to prevent this. | ||||
// Furthermore, the UNC prefix: \\ is not required and always removed. | // 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: | startNetShareGetInfo: | ||||
@@ -338,7 +335,7 @@ namespace Alphaleonis.Win32.Network | |||||
SafeGlobalMemoryBufferHandle safeBuffer; | SafeGlobalMemoryBufferHandle safeBuffer; | ||||
uint structureLevel = Convert.ToUInt16(shareLevel, CultureInfo.InvariantCulture); | 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) | using (safeBuffer) | ||||
{ | { | ||||
@@ -19,7 +19,6 @@ | |||||
* THE SOFTWARE. | * THE SOFTWARE. | ||||
*/ | */ | ||||
using System; | |||||
using System.Diagnostics.CodeAnalysis; | using System.Diagnostics.CodeAnalysis; | ||||
using System.Runtime.InteropServices; | using System.Runtime.InteropServices; | ||||
using System.Security; | using System.Security; | ||||
@@ -1,7 +1,7 @@ | |||||
//------------------------------------------------------------------------------ | //------------------------------------------------------------------------------ | ||||
// <auto-generated> | // <auto-generated> | ||||
// This code was generated by a tool. | // 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 | // Changes to this file may cause incorrect behavior and will be lost if | ||||
// the code is regenerated. | // the code is regenerated. | ||||
@@ -30,14 +30,13 @@ namespace Alphaleonis.Win32 | |||||
{ | { | ||||
#region Private Fields | #region Private Fields | ||||
private int m_capacity; | |||||
private readonly int m_capacity; | |||||
#endregion | #endregion | ||||
#region Constructors | #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; | private ulong m_hash; | ||||
/// <summary>Initializes a new instance of <see cref="Crc64"/> </summary> | /// <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) | private Crc64(ulong polynomial, ulong seed) | ||||
{ | { | ||||
m_table = InitializeTable(polynomial); | m_table = InitializeTable(polynomial); | ||||
this.m_seed = m_hash = seed; | |||||
m_seed = m_hash = seed; | |||||
} | } | ||||
/// <summary> | /// <summary> | ||||
@@ -106,11 +105,13 @@ namespace Alphaleonis.Win32.Security | |||||
private static ulong CalculateHash(ulong seed, ulong[] table, IList<byte> buffer, int start, int size) | private static ulong CalculateHash(ulong seed, ulong[] table, IList<byte> buffer, int start, int size) | ||||
{ | { | ||||
var hash = seed; | var hash = seed; | ||||
for (var i = start; i < start + size; i++) | |||||
for (var i = start; i < start + size; i++) | |||||
unchecked | unchecked | ||||
{ | { | ||||
hash = (hash >> 8) ^ table[(buffer[i] ^ hash) & 0xff]; | hash = (hash >> 8) ^ table[(buffer[i] ^ hash) & 0xff]; | ||||
} | } | ||||
return hash; | return hash; | ||||
} | } | ||||
@@ -151,12 +152,11 @@ namespace Alphaleonis.Win32.Security | |||||
var createTable = new ulong[256]; | var createTable = new ulong[256]; | ||||
for (var i = 0; i < 256; ++i) | for (var i = 0; i < 256; ++i) | ||||
{ | { | ||||
var entry = (ulong)i; | |||||
var entry = (ulong) i; | |||||
for (var j = 0; j < 8; ++j) | 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; | createTable[i] = entry; | ||||
} | } | ||||
@@ -43,7 +43,7 @@ namespace Alphaleonis.Win32.Security | |||||
if (privilegeName == null) | if (privilegeName == null) | ||||
throw new ArgumentNullException("privilegeName"); | throw new ArgumentNullException("privilegeName"); | ||||
_mPrivilege = privilegeName; | |||||
EnabledPrivilege = privilegeName; | |||||
AdjustPrivilege(true); | AdjustPrivilege(true); | ||||
} | } | ||||
@@ -55,12 +55,12 @@ namespace Alphaleonis.Win32.Security | |||||
{ | { | ||||
try | try | ||||
{ | { | ||||
if (_mPrivilege != null) | |||||
if (EnabledPrivilege != null) | |||||
AdjustPrivilege(false); | AdjustPrivilege(false); | ||||
} | } | ||||
finally | finally | ||||
{ | { | ||||
_mPrivilege = null; | |||||
EnabledPrivilege = null; | |||||
} | } | ||||
} | } | ||||
@@ -71,31 +71,23 @@ namespace Alphaleonis.Win32.Security | |||||
{ | { | ||||
using (WindowsIdentity currentIdentity = WindowsIdentity.GetCurrent(TokenAccessLevels.Query | TokenAccessLevels.AdjustPrivileges)) | 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 | #endregion // Privilege | ||||
}; | |||||
} | |||||
} | } |
@@ -222,8 +222,8 @@ namespace Alphaleonis.Win32 | |||||
//public const uint ERROR_SIGNAL_REFUSED = 156; | //public const uint ERROR_SIGNAL_REFUSED = 156; | ||||
//public const uint ERROR_DISCARDED = 157; | //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_THREADID_ADDR = 159; | ||||
//public const uint ERROR_BAD_ARGUMENTS = 160; | //public const uint ERROR_BAD_ARGUMENTS = 160; | ||||
@@ -259,7 +259,7 @@ namespace Alphaleonis.Win32 | |||||
//public const uint ERROR_INFLOOP_IN_RELOC_CHAIN = 202; | //public const uint ERROR_INFLOOP_IN_RELOC_CHAIN = 202; | ||||
/// <summary>(203) The system could not find the environment option that was entered.</summary> | /// <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_NO_SIGNAL_SENT = 205; | ||||
//public const uint ERROR_FILENAME_EXCED_RANGE = 206; | //public const uint ERROR_FILENAME_EXCED_RANGE = 206; | ||||
@@ -320,7 +320,7 @@ namespace Alphaleonis.Win32 | |||||
//public const uint ERROR_IO_INCOMPLETE = 996; | //public const uint ERROR_IO_INCOMPLETE = 996; | ||||
/// <summary>(997) Overlapped I/O operation is in progress.</summary> | /// <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_NOACCESS = 998; | ||||
//public const uint ERROR_SWAPERROR = 999; | //public const uint ERROR_SWAPERROR = 999; | ||||
@@ -449,7 +449,7 @@ namespace Alphaleonis.Win32 | |||||
//public const uint ERROR_JOURNAL_ENTRY_DELETED = 1181; | //public const uint ERROR_JOURNAL_ENTRY_DELETED = 1181; | ||||
/// <summary>(1200) The specified device name is invalid.</summary> | /// <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_CONNECTION_UNAVAIL = 1201; | ||||
//public const uint ERROR_DEVICE_ALREADY_REMEMBERED = 1202; | //public const uint ERROR_DEVICE_ALREADY_REMEMBERED = 1202; | ||||
@@ -460,7 +460,7 @@ namespace Alphaleonis.Win32 | |||||
//public const uint ERROR_NOT_CONTAINER = 1207; | //public const uint ERROR_NOT_CONTAINER = 1207; | ||||
/// <summary>(1208) An extended error has occurred.</summary> | /// <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_GROUPNAME = 1209; | ||||
//public const uint ERROR_INVALID_COMPUTERNAME = 1210; | //public const uint ERROR_INVALID_COMPUTERNAME = 1210; | ||||
@@ -477,7 +477,7 @@ namespace Alphaleonis.Win32 | |||||
//public const uint ERROR_DUP_DOMAINNAME = 1221; | //public const uint ERROR_DUP_DOMAINNAME = 1221; | ||||
/// <summary>(1222) The network is not present or not started.</summary> | /// <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_CANCELLED = 1223; | ||||
//public const uint ERROR_USER_MAPPED_FILE = 1224; | //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 | // http://msdn.microsoft.com/en-us/library/windows/desktop/aa370674%28v=vs.85%29.aspx | ||||
/// <summary>(0) The operation completed successfully.</summary> | /// <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> | ///// <summary>The workstation driver is not installed.</summary> | ||||
//public const uint NERR_NetNotStarted = 2102; | //public const uint NERR_NetNotStarted = 2102; | ||||
@@ -3559,7 +3559,7 @@ namespace Alphaleonis.Win32 | |||||
//public const uint NERR_SyncRequired = 2249; | //public const uint NERR_SyncRequired = 2249; | ||||
/// <summary>(2250) The network connection could not be found.</summary> | /// <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> | ///// <summary>This asg_type is invalid.</summary> | ||||
//public const uint NERR_BadAsgType = 2251; | //public const uint NERR_BadAsgType = 2251; | ||||
@@ -3646,7 +3646,7 @@ namespace Alphaleonis.Win32 | |||||
//public const uint NERR_MultipleNets = 2300; | //public const uint NERR_MultipleNets = 2300; | ||||
/// <summary>(2310) This shared resource does not exist.</summary> | /// <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> | ///// <summary>This device is not shared.</summary> | ||||
//public const uint NERR_DeviceNotShared = 2311; | //public const uint NERR_DeviceNotShared = 2311; | ||||
@@ -1,3 +1,3 @@ | |||||
<?xml version="1.0"?> | <?xml version="1.0"?> | ||||
<configuration> | <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> | <DebugSymbols>true</DebugSymbols> | ||||
<DebugType>full</DebugType> | <DebugType>full</DebugType> | ||||
<Optimize>false</Optimize> | <Optimize>false</Optimize> | ||||
<OutputPath>..\..\..\..\..\Program Files\WindowsPowerShell\Modules\NTFSSecurity\</OutputPath> | |||||
<OutputPath>..\..\..\..\..\..\Program Files\WindowsPowerShell\Modules\NTFSSecurity\</OutputPath> | |||||
<DefineConstants>TRACE;DEBUG</DefineConstants> | <DefineConstants>TRACE;DEBUG</DefineConstants> | ||||
<ErrorReport>prompt</ErrorReport> | <ErrorReport>prompt</ErrorReport> | ||||
<WarningLevel>4</WarningLevel> | <WarningLevel>4</WarningLevel> | ||||