Open blackeyed7 opened 3 years ago
Yes, you do need to set this field if the directory exist. This is expected and documented.
Could you explain a little more where you added this code ?
I've read more code in C# mirror, and I thought its should not be fixed in this way, but I found its more complex than I thought, I think I need more help for this
the key code in C mirror is this (line 273) if (fileAttr != INVALID_FILE_ATTRIBUTES && fileAttr & FILE_ATTRIBUTE_DIRECTORY) { if (CreateOptions & FILE_NON_DIRECTORY_FILE) { DbgPrint(L"\tCannot open a dir as a file\n"); return STATUS_FILE_IS_A_DIRECTORY;
it seems that user software tring to open a directory as a file, so then here it tells that this FILE IS A DIRECTORY, then everything's fine.
But there is no STATUS_FILE_IS_A_DIRECTORY in Dokan.NET I tried to add same long code, and edit the code in CreateFile
switch (mode)
{
case FileMode.Open:
if (pathExists)
{
// check if driver only wants to read attributes, security info, or open directory
if (readWriteAttributes || pathIsDirectory)
{
if (pathIsDirectory && (access & FileAccess.Delete) == FileAccess.Delete
&& (access & FileAccess.Synchronize) != FileAccess.Synchronize)
//It is a DeleteFile request on a directory
return Trace(nameof(CreateFile), fileName, info, access, share, mode, options,
attributes, DokanResult.AccessDenied);
info.IsDirectory = pathIsDirectory;
info.Context = new object();
// must set it to something if you return DokanError.Success
return Trace(nameof(CreateFile), fileName, info, access, share, mode, options,
attributes, DokanResult.FILE_IS_A_DIRECTORY);
}
}
then I no longer able to open the any directory in my mounted driver, it says "denied"
Yes, you do need to set this field if the directory exist. This is expected and documented.
Could you explain a little more where you added this code ?
I was adding that code at the very begining of the CreateFile method, it fixed the problem that my user software met when using mirror sample for Dokan.NET
but I am not able to use this fix code in my own code, it is a little complex the fix code FileAttributes attr = File.GetAttributes(filePath); this will throw exception reading "destkop.ini", even I use MountManger, it still happens (not suppose to happen with MountManger?) and if I catch it, still the user software recognize the directory as a file (so my pre problem still there)
found a workaround, not sure if any side effect so far
switch (mode)
{
case FileMode.Open:
if (pathExists)
{
// check if driver only wants to read attributes, security info, or open directory
if (readWriteAttributes || pathIsDirectory)
{
if (pathIsDirectory && (access & FileAccess.Delete) == FileAccess.Delete
&& (access & FileAccess.Synchronize) != FileAccess.Synchronize)
//It is a DeleteFile request on a directory
return Trace(nameof(CreateFile), fileName, info, access, share, mode, options,
attributes, DokanResult.AccessDenied);
info.IsDirectory = pathIsDirectory;
info.Context = new object();
// must set it to something if you return DokanError.Success
if (pathIsDirectory)
{
if (access == FileAccess.GenericRead)
return Trace(nameof(CreateFile), fileName, info, access, share, mode, options, attributes,
(NtStatus)0xC00000BAL);
}
return Trace(nameof(CreateFile), fileName, info, access, share, mode, options,
attributes, DokanResult.Success);
}
}
To properly handle this issue we need to support FILE_NON_DIRECTORY_FILE
which is not part of the official FileOptions
enum. So we would need to extend the current enum and the others present in NtCreateFile
.
Also add STATUS_FILE_IS_A_DIRECTORY
to the NtStatus:
https://github.com/dokan-dev/dokan-dotnet/blob/master/DokanNet/NtStatus.cs
if (pathIsDirectory)
{
if (access == FileAccess.GenericRead) <=== createOptions & FileOptions.NonDirectoryFile
return Trace(nameof(CreateFile), fileName, info, access, share, mode, options, attributes,
(NtStatus)0xC00000BAL);
}
GenericRead
is too wild and will create many issues.
Thanks @blackeyed7,
I was experiencing the same issue when scanning my virtual drive with log4jscanner.
If I ran: log4jscanner.exe N:\
it would instantly return:
2022/01/20 11:37:59 log4jscanner.go:120: Error: scanning N:\: readdir N:\/.: The system cannot find the path specified.
So to scanner seems to enumerate the drive in an unusual way. Also, the scan would run fine on a virtual drive provided through mirror.exe. Those two facts suggested an issue with dokan-dotnet
which led me to your post. Thanks!
Thanks @Liryna, I added that block of code to CreateFile()
and now log4jscanner processes the drive fine.
in CreateFile method info.IsDirectory not working (not sure if its 100% fail) I see the C mirror code has a check there, so I added check code on mine too