From: Corinna Vinschen on 25 Jan 2007 11:06 Hi, I have some code which is supposed to delete a file. If the file is in use, the file gets moved to some other directory so that it disappears from directory listings of the parent directory. The code is basically done like this (some code removed for clarity): #define NO_SHARE_FLAGS 0 #define ALL_SHARING_FLAGS (FILE_SHARE_READ \ | FILE_SHARE_WRITE \ | FILE_SHARE_DELETE) bool move = false; status = ZwOpenFile (..., DELETE, ..., NO_SHARE_FLAGS, FILE_DELETE_ON_CLOSE); if (status == STATUS_SHARING_VIOLATION) { /* Oops, file is in use, open with full share flags and mark for moving away. */ status = ZwOpenFile (..., DELETE, ..., ALL_SHARING_FLAGS, FILE_DELETE_ON_CLOSE); move = true; } if (NT_SUCCESS (status)) { if (move) { prepare_rename_information (filename, dir_to_move_to); status = ZwSetInformationFile (..., FileRenameInformation); } status = ZwClose (); } This code works fine... for files. Now I tried to reuse the code for removing directories. Consider another piece of code (no matter if in the same process or another one) has opened the directory for a later call to ZwQueryDirectoryFile: status = ZwOpenFile (..., SYNCHRONIZE | FILE_LIST_DIRECTORY, ..., ALL_SHARING_FLAGS, FILE_SYNCHRONOUS_IO_NONALERT | FILE_OPEN_FOR_BACKUP_INTENT | FILE_DIRECTORY_FILE); What happens now in the above code to remove the file/directory is this. The first call to ZwOpenFile fails, as expected, because the dir has an open handle. The second call to ZwOpenFile succeeds. So the "move" flag gets set and ZwSetInformationFile(FileRenameInformation) is called, and fails! The status code is 0xc0000022, STATUS_ACCESS_DENIED. Why does the move fail? For the open handle to this directory it shouldn't matter in which parent directory the directory resides, the same way as it doesn't matter to a handle to an open file. And more important: Is there a way around this? I searched for flags to ZwOpenFile or flags to ZwSetInformationFile which could help in this matter, but to no avail. Obviously one way around this is to defer the call to ZwOpenFile in the code trying to enumerate the directory to the point where the first directory entry is going to be read. However, this only moves the problem to a later point in execution, it doesn't solve the problem in a generic way. So, I'm still looking for a generic solution. Thanks for any help, Corinna -- Corinna Vinschen Cygwin Project Co-Leader Red Hat
From: "Jeffrey Tan[MSFT]" on 26 Jan 2007 03:18 Hi Corinna, It seems that you are using undocumented Windows API ZwSetInformationFile with FileRenameInformation parameter to move the files/directories. It works well for the file but fail for the directory. Normally, MSDN support does not provide official support for undocumented API issues. Anyway, I will try my best to help you. Have you tried this with more other directories? In this scenario, I suspect the original code that uses the file may passed 0 as the "ShareAccess" parameter, which does not share you to use FileRenameInformation for the locking file. Normally, you may use Process Monitor from the link below to monitor the directory access of ZwSetInformationFile calling, there will be a "Access Deny" record: http://www.microsoft.com/technet/sysinternals/ProcessesAndThreads/processmon itor.mspx Process Monitor will also capture a call stack of this error access, then you may set up the symbol server correctly and provide the symbolic call stack for this failure here. It should be informative. Finally, is it possible for you to create a little sample project with steps to help me reproduce the problem? Then I will try to give it a troubleshooting. Thanks. Best regards, Jeffrey Tan Microsoft Online Community Support ================================================== Get notification to my posts through email? Please refer to http://msdn.microsoft.com/subscriptions/managednewsgroups/default.aspx#notif ications. Note: The MSDN Managed Newsgroup support offering is for non-urgent issues where an initial response from the community or a Microsoft Support Engineer within 1 business day is acceptable. Please note that each follow up response may take approximately 2 business days as the support professional working with you may need further investigation to reach the most efficient resolution. The offering is not appropriate for situations that require urgent, real-time or phone-based interactions or complex project analysis and dump analysis issues. Issues of this nature are best handled working with a dedicated Microsoft Support Engineer by contacting Microsoft Customer Support Services (CSS) at http://msdn.microsoft.com/subscriptions/support/default.aspx. ================================================== This posting is provided "AS IS" with no warranties, and confers no rights.
From: Corinna Vinschen on 26 Jan 2007 07:28 Hi Jeffrey, Jeffrey Tan[MSFT] wrote: > Hi Corinna, > > It seems that you are using undocumented Windows API ZwSetInformationFile > with FileRenameInformation parameter to move the files/directories. It Sigh. I didn't even realize that this is an undocumented API until you just told me. I hope you can understand my point here, though. The idea is to have a generic delete/move operation which allows POSIX delete semantics while maintaining a speedy operation in bulk remove operations like the POSIX `rm -rf' case which consists of lots of unlink/rmdir calls. The big advantage of using the ntdll API here is the fact that the file has to be opened only once and the handle can then be used for the whole operation. There's just no comparable win32 API to implement unlink/rmdir this efficient. > [...] > Have you tried this with more other directories? In this scenario, I > suspect the original code that uses the file may passed 0 as the > "ShareAccess" parameter, which does not share you to use > FileRenameInformation for the locking file. If you look into the code snippets in my original posting, you see that the other handle has been opened with all sharing flags set. Also keep in mind that the second ZwOpenFile in the unlink code succeeded, which means, there was an open handle, but that handle didn't disallow sharing. It's the subsequent FileRenameInformation which fails with STATUS_ACCESS_DENIED, not the ZwOpenFile. > Normally, you may use Process Monitor from the link below to monitor the > directory access of ZwSetInformationFile calling, there will be a "Access > Deny" record: > http://www.microsoft.com/technet/sysinternals/ProcessesAndThreads/processmon > itor.mspx > [...] This was a very valuable hint, which actually solved my problem! I didn't think of testing with other applications but while looking into the output of Process Monitor I tried to move the file using Explorer which, to my surprise, succeeded when using FileRenameInformation. By comparing the different flags used by my unlink code and used by Explorer, I found the cause of the problem. Apparently, the semantics of FILE_DELETE_ON_CLOSE are different between files and directories. When the directory is opened with FILE_DELETE_ON_CLOSE, then FileRenameInformation fails. When the directory is not opened with FILE_DELETE_ON_CLOSE, FileRenameInformation succeeds. So, what my code basically does now is this: ZwOpenFile (..., NO_SHARING, flags | (dir ? 0 : FILE_DELETE_ON_CLOSE); if (open_failed) { ZwOpenFile (..., ALL_SHARING, flags | (dir ? 0 : FILE_DELETE_ON_CLOSE); have_to_move = true; } if (have_to_move) ZwSetInformationFile (..., FileRenameInformation); if (dir) ZwSetInformationFile (..., FileDispositionInformation); ZwClose (); Is there any chance to learn the reason why open(delete-on-close); move(); close(); works for files, but emits an access denied error in the move operation on directories? Thanks, Corinna -- Corinna Vinschen Cygwin Project Co-Leader Red Hat
From: Corinna Vinschen on 27 Jan 2007 05:59 Corinna Vinschen wrote: > Jeffrey Tan[MSFT] wrote: >> It seems that you are using undocumented Windows API ZwSetInformationFile >> with FileRenameInformation parameter to move the files/directories. It > > Sigh. I didn't even realize that this is an undocumented API until > you just told me. [...] Btw., it's irritating that ZwSetInformationFile (FileRenameInformation) is "undocumented". FltSetInformationFile (FileRenameInformation) as well as the FILE_RENAME_OPERATION structure *are* documented and both refer to ZwSetInformationFile in terms of the FileRenameInformation class, see http://msdn2.microsoft.com/en-us/library/aa488684.aspx and http://msdn2.microsoft.com/en-us/library/ms791548.aspx(*). I don't quite understand why such a simple and basic operation should be treated as undocumented. It doesn't do anything hidden, dangerous, or mysterious. Corinna (*) The FILE_RENAME_OPERATION documentation isn't quite correct. It claims "A file cannot be renamed if it has any open handles, unless it is only open because of a [...] (oplock) [...]." A file or directory can be renamed regardless if it has an open handle or not, as long as the open handle is opened for sharing. -- Corinna Vinschen Cygwin Project Co-Leader Red Hat
From: "Jeffrey Tan[MSFT]" on 29 Jan 2007 08:01 Hi Corinna, Thanks for your feedback! Glad to see the Process Monitor makes sense for you. Your troubleshooting information and result are also informative to me and the community. Yes, I see the 2 links for FltSetInformationFile, ZwSetInformationFile. However, these 2 MSDN links are both for DDK. They are both exported by ntoskrnl.exe, not user-mode modules. The reason I say they are undocumented is that the ZwSetInformationFile you are using is the user-mode undocumented API exported by ntdll. Microsoft did not document these APIs since these APIs may not keep backward compatibility, and may be changed between each OS release. Regarding the reason of FILE_DELETE_ON_CLOSE fails for directory with FileRenameInformation, I want to know which account do you execute the code? Does it have delete child special permission on the directory? I am not familar with the internal work of ZwSetInformationFile with FileRenameInformation, so I tried to review the source code of ntoskrnl.exe ZwSetInformationFile API for FileRenameInformation. I find it did not do much magic, but pass the work to the file system driver with IoCallDriver calling. Sorry, I am not a DDK expert, so I will not dig more into to the File System driver level. Anyway, I will try to consult this issue with file system team internally for explanation. I will feedback any information here ASAP. Thanks for your understanding. Best regards, Jeffrey Tan Microsoft Online Community Support ================================================== Get notification to my posts through email? Please refer to http://msdn.microsoft.com/subscriptions/managednewsgroups/default.aspx#notif ications. Note: The MSDN Managed Newsgroup support offering is for non-urgent issues where an initial response from the community or a Microsoft Support Engineer within 1 business day is acceptable. Please note that each follow up response may take approximately 2 business days as the support professional working with you may need further investigation to reach the most efficient resolution. The offering is not appropriate for situations that require urgent, real-time or phone-based interactions or complex project analysis and dump analysis issues. Issues of this nature are best handled working with a dedicated Microsoft Support Engineer by contacting Microsoft Customer Support Services (CSS) at http://msdn.microsoft.com/subscriptions/support/default.aspx. ================================================== This posting is provided "AS IS" with no warranties, and confers no rights.
|
Next
|
Last
Pages: 1 2 3 4 5 Prev: RasEditPhoneBookEntry and Vista Next: GetCurrentHwProfile determining dockability on Vista |