dokan-dev / dokany

User mode file system library for windows with FUSE Wrapper
http://dokan-dev.github.io
5.29k stars 665 forks source link

DeleteOnClose vs FILE_FLAG_DELETE_ON_CLOSE #18

Closed suy closed 9 years ago

suy commented 9 years ago

I've been puzzled by some hours after realizing that Windows Explorer on Windows 8 was removing files without actually ever calling the DeleteFile operation, nor receiving a Cleanup or Close operation with DeleteOnClose set.

I've found the explanations of the issue here:

So it seems that since Windows 8 there is another way to delete files, and is opening them with FILE_FLAG_DELETE_ON_CLOSE in the dwFlagsAndAttributes parameter of CreateFile. Dokan doesn't support that out of the box, but there are easy to work around.

  1. Keep in the application the state of that flag from CreateFile to Cleanup, and remember to delete the file even if DeleteOnClose is not set in the DokanFileInfo structure. This is difficult on the file system application, and requires checking two flags for the same purpose, one coming from Dokan, other from the application itself.
  2. Check the flag on CreateFile in the application and set DeleteOnClose to TRUE appropiately. This is easy, but it didn't work for me. Probably Dokan overwrites it, as the application is only supposed to write in the Context variable.
  3. Return an error in CreateFile if the flag is set. Windows Explorer will try to delete the file using DeleteFile as a fallback. This worked for me, but I don't know if it's the proper behaviour, and it could fail with other applications.

The other possibility is actually fixing it in Dokan, either by ensuring that workardound 2 can be done, or by setting DeleteOnClose like in the other cases.

If you think it should be done in the application, let me know, and I'll update the documentation and close the issue.

Thank you!

Liryna commented 9 years ago

@suy "FILE_FLAG_DELETE_ON_CLOSE in the dwFlagsAndAttributes parameter of CreateFile. Dokan doesn't support that out of the box, but there are easy to work around." If I remember Dokan already give you the information during CreateFile. https://github.com/dokan-dev/dokany/blob/8b7742fae5b78af4a21ee42201a7fcb1517a2004/dokan/create.c#L98

This Windows 10 (= 8.1) sample give us a over view of the officiel behaviour for detecting the delete file operation. https://github.com/Microsoft/Windows-driver-samples/tree/master/filesys/miniFilter/delete

It monitors IRP_MJ_CREATE requests for the FILE_DELETE_ON_CLOSE flag. Also, it detects IRP_MJ_SET_INFORMATION requests for setting FileDispositionInformation. The sample also illustrates how to handle racing deletes (in the form of multiple parallel IRP_MJ_SET_INFORMATION operations), and how to distinguish deletion of an entire file from deletion of just one stream of the file.

I also think that it is the application that should keep a information to handle automaticaly the delete on close.

Maybe we even should remove the flag during CloseFile for the < 8 Windows version to have a "standard" behaviour ?

suy commented 9 years ago

Removing the DeleteOnClose flag would be a source and binary incompatible change with old applications. That's why I was thinking of using it instead (either setting it in the application or the library/driver). That might be able to "upgrade" old applications that weren't aware of the flag, although you probably will know better if this is safe.

If you think it's the application's duty to do so, I'll implement it in mine, and update the docs.

One question remains, though: how comes that Microsoft introduced this safely? Isn't it breaking all other file system drivers as well?

Liryna commented 9 years ago

You are right. Remove the flag would break compatibility.

I have look how to add the flag during close event on Win > 8. DeleteOnClose is set from the EventContext information: https://github.com/dokan-dev/dokany/blob/741198c10b52bd1bf38eb389197d5c8bb9682f01/dokan/dokan.c#L448

The EvenContext come from DeviceIoControl (dokan driver). https://github.com/dokan-dev/dokany/blob/741198c10b52bd1bf38eb389197d5c8bb9682f01/dokan/dokan.c#L291

I guess Windows break the compatibility :D or the officiel behaviour never was to check delete on close.

The EvenContext is a new instance for every IO call. Thats why it is impossible to store the DeleteOnClose inside.

We should find a way to store it in a clean way inside the DokanLoop

Liryna commented 9 years ago

Added with 770d2a76a97f7cf86002660d44c9aaeba8f474f0 from https://github.com/BenjaminKim/dokanx/pull/45

The logic is different and more simple :smile: and it work ! :+1:

Thanks @marinkobabic

suy commented 9 years ago

It took me some time to be able to test, but so far, yes, this seems to work. :-) Thank you!

I don't understand, though, what would change the other parts of the change that Marinko did. I see the DeleteFile operation being called before the cleanup anyway.