Unset FILE_FLAG_DELETE_ON_CLOSE

FILE_FLAG_DELETE_ON_CLOSE gives atomicity to the Create delete operations. But is there a way to unset/reset/clear this flag once set, if the user believed they needed to not delete the file on close after all? I am checking this, but i am not sure if FILE_DISPOSITION_DO_NOT_DELETE or FILE_DISPOSITION_ON_CLOSE will work. https://docs.microsoft.com/en-us/windows-hardware/drivers/ddi/ntddk/ns-ntddk-_file_disposition_information_ex Any pointers would be much appreciated.

If you look at the bottom of the page you cited above you would see that ZwSetInformationFile allows you to change the file disposition. FltSetInformationFile is a wrapper for this for minifilters.

@Don_Burn said:
If you look at the bottom of the page you cited above you would see that ZwSetInformationFile allows you to change the file disposition. FltSetInformationFile is a wrapper for this for minifilters.

Thanks Don. Like with anything related to File systems, there are too many edge cases, and didn’t want to break something which I didn’t intend to by using the wrong flags.

That is available on W10 1709+ only.
On earlier OSes, you can only query FileModeInformation, but IIRC no FSes
process changing it.

@Dejan_Maksimovic said:
That is available on W10 1709+ only.
On earlier OSes, you can only query FileModeInformation, but IIRC no FSes
process changing it.

Oh, is it? Doesnt say anywhere on the page though.

That is available on W10 1709+ only.

How? As far as I understand FILE_FLAG_DELETE_ON_CLOSE cannot be unset… For example, this code tries to undo the flag but the file is still deleted:

int main()
{
	HANDLE FileHandle;
	BOOLEAN DeleteFlag = FALSE;
	FILE_DISPOSITION_INFO_EX InfoEx = { 0 };

	FileHandle = CreateFileA("HelloWorld", FILE_ALL_ACCESS, FILE_SHARE_READ, NULL,
							 CREATE_NEW, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_DELETE_ON_CLOSE, NULL);
	if (FileHandle == INVALID_HANDLE_VALUE) {
		printf("CreateFileA failed\n");
		return -1;
	}

	if (!SetFileInformationByHandle(FileHandle, FileDispositionInfo, &DeleteFlag,
									sizeof(DeleteFlag))) {
		printf("SetFileInformationByHandle failed\n");
		return -1;
	}

	if (!SetFileInformationByHandle(FileHandle, FileDispositionInfoEx, &InfoEx,
							         sizeof(InfoEx))) {
		printf("SetFileInformationByHandle failed\n");
		return -1;
	}

	CloseHandle(FileHandle);
}

If you write a minifilter you can remove the FILE_DELETE_ON_CLOSE flag in the pre-create callback then set FileDispositionInformation so it can be unset later…

Read this for more info about the details: https://fsfilters.blogspot.com/2011/10/file-deletion.html

On file systems that support it (e.g. NTFS in version 1607 and later), setting FileDispositionInformationEx with Flags == (FILE_DISPOSITION_DO_NOT_DELETE | FILE_DISPOSITION_ON_CLOSE) will clear delete-on-close state on that handle. Note that FILE_DISPOSITION_DO_NOT_DELETE is not an actual flag but rather for readability.

The combination (FILE_DISPOSITION_DELETE | FILE_DISPOSITION_ON_CLOSE) expresses setting delete-on-close state on that handle. We currently fail that combination with STATUS_NOT_SUPPORTED if the handle was not already in delete-on-close state, because we didn’t want to introduce a new way to delete into the filter ecosystem unless there’s a real need. However we succeed the combination if the handle is already in delete-on-close state (the trivial case), so that difference could be used to infer the state.

un setting delete on close seems like a dangerous feature unless the handle has delete access rights

@craigbarkhouse Thank you for the explanation, I didn’t know that’s possible