Copied from internal bug 402782
System.IO.Directory.Delete recursive delete will not recurse through directory placeholders as it should (directory placeholders are a feature of GvFlt and the
container filter).
Christian Allred [callred] found that the Delete code "will avoid trying to enumerate directories that are any kind of reparse point, rather than just name surrogates ... It should be fixed to check for the name surrogate bit on the reparse tag, same as rmdir /s does"
See: http://ddindex/?rightProject=mscorlib&file=system%5cio%5cdirectory.cs&line=1324)
rmdir code
//
// We now enumerate and delete children iff:
// directory and not reparse/namesurrogate
//
if (IsDirectory( find_data.dwFileAttributes )
&& !(IsReparse( find_data.dwFileAttributes ) && IsReparseTagNameSurrogate( find_data.dwReserved0 ))) {
...
// (Enumerate, deleting files and recursing into directories)
...
}
return RemoveDirectoryForce(pszDirectory);
...
Rmdir /s checks the name surrogate bit using IsReparseTagNameSurrogate, which is in ntifs.h. It is defined as:
#define IsReparseTagNameSurrogate(_tag) (
((_tag) & 0x20000000)
)
If you're doing a FindFirst/FindNext, the _tag value is the dwReserved0 field of the WIN32_FIND_DATA structure. That is how rmdir /s does its check:
//
// We now enumerate and delete children iff:
// directory and not reparse/namesurrogate
//
if (IsDirectory( find_data.dwFileAttributes )
&& !(IsReparse( find_data.dwFileAttributes ) && IsReparseTagNameSurrogate( find_data.dwReserved0 ))) {
...
// (Enumerate, deleting files and recursing into directories)
...
}
return RemoveDirectoryForce(pszDirectory);
...
Forgot to mention, the name surrogate bit is set on directory junctions, symlinks, etc. So having this check correctly identifies other types of reparse points that a recursive delete would not want to recurse in to.
Copied from internal bug 402782
System.IO.Directory.Delete recursive delete will not recurse through directory placeholders as it should (directory placeholders are a feature of GvFlt and the
container filter).
Christian Allred [callred] found that the Delete code "will avoid trying to enumerate directories that are any kind of reparse point, rather than just name surrogates ... It should be fixed to check for the name surrogate bit on the reparse tag, same as rmdir /s does"
See: http://ddindex/?rightProject=mscorlib&file=system%5cio%5cdirectory.cs&line=1324)
rmdir code
...
Rmdir /s checks the name surrogate bit using IsReparseTagNameSurrogate, which is in ntifs.h. It is defined as:
#define IsReparseTagNameSurrogate(_tag) (
((_tag) & 0x20000000)
)
If you're doing a FindFirst/FindNext, the _tag value is the dwReserved0 field of the WIN32_FIND_DATA structure. That is how rmdir /s does its check:
...
Forgot to mention, the name surrogate bit is set on directory junctions, symlinks, etc. So having this check correctly identifies other types of reparse points that a recursive delete would not want to recurse in to.