Determining the ability to delete a file

This is a discussion on Determining the ability to delete a file within the Windows Programming forums, part of the Platform Specific Boards category; I need to be able to determine if I can delete a file in NT/2000/XP, before actually deleteing it. The ...

Determining the ability to delete a file

I need to be able to determine if I can delete a file in NT/2000/XP, before actually deleteing it. The problem is, other applications may already have an open handle to the file. This causes any attempt to delete the file in an NT based OS to fail.

The only thing I can think of is to try to rename the file. This should also fail if another process has an open handle to the file. But I would rather not do this for every file since I maybe processing thousands of files.

The reason...

The reason I need to know before I delete is that I need to zero the file out before deleting. If I zero the file out, then try to delete and I can't delete, then I don't want to delete the file. But now the file is already zero'd and worthless.

I wanted to try to find a way to determine this other than renaming, because the program may be testing thousands of files, and I imagine that to rename thousands of files and rename them back would be a waste of time, especially since the FAT would have to updated on every name change.

How about reading data to memory,
try deleteing it,
then you can write the data back to the file if needed or fill it with rubbish

Code:

hFile=CreateFile(.................);//open existing file
//error check to see if opened
iSize=GetFileSize(hFile,NULL);//small files
//alloc mem this size and error check
//read file for this size and error check
//CloseHandle(hFile);
//find if file will delete
//free the memory

It's not locked in the since that a process has called LockFile(), it's just the file has been opened for reading by another process. In NT/2000/XP, if a file is open by another process already, another process can not delete it.

The process can write to the file, because the other file only open it for reading.

HANDLE hFile;
/* Try to open the file with no sharing rights. This will cause
* an error if another program has it open. Request access to
* write to and delete the file. */
hFile = CreateFile(fileName,GENERIC_WRITE | DELETE,0,NULL,OPEN_EXISTING,0,NULL);
if (hFile == INVALID_HANDLE_VALUE) {
if (GetLastError() == ERROR_SHARING_VIOLATION) do something; /* Someone has it open */
else do something; /* probable ERROR_FILE_NOT_FOUND or ERROR_ACCESS_DENIED */
}
else {
//do stuff
CloseHandle(hFile);
//DeleteFile()
}
}

It should also be noted that in the scenario you outline the zeros will probably never hit the harddisk without a call to FlushFileBuffers.

Trying rename, write, etc to test if a file can be deleted may not work on NTFS as each of these permissions can be set separately.

In my previous example, there is a miniscule chance that another process could open the file between CloseHandle and DeleteFile. To stop this you may wish to use the FILE_FLAG_DELETE_ON_CLOSE flag in CreateFile and then do a final check that the file is deleted after CloseHandle.

I believe that the DELETE flag for CreateFile() is based on user access rights, and not on current file operations. Therefore, the user may have the rights to delete the file, but still would not be able to because it is already opened by another process.

Setting the dwShareMode argument to 0 is what guarantees that your file is not open by another process.

MSDN:
You cannot request a sharing mode that conflicts with the access mode specified in a previous open request whose handle is still open.

0 conflicts with everything.

Determining security access with the dwDesiredAccess argument at the same time is a bonus.

For reference, I wrote a sample for using ODBC with excel that required the excel file not be open (if an open excel file is altered bad consequences ensue). This was my function:

Code:

BOOL isFileOpen(LPTSTR fileName) {
/* Check if another program has a file open */
HANDLE hFile;
/* Try to open the file with no sharing rights. This will cause
* an error if another program has it open */
hFile = CreateFile(fileName,GENERIC_READ,0,NULL,OPEN_EXISTING,0,NULL);
if (hFile == INVALID_HANDLE_VALUE) {
if (GetLastError() == ERROR_SHARING_VIOLATION) return TRUE; /* Someone has it open */
else return FALSE; /* probable ERROR_FILE_NOT_FOUND */
}
else {
CloseHandle(hFile);
return FALSE;
}
}