If FILE_SKIP_COMPLETION_PORT_ON_SUCCESS
is set on a file handle that is bound to an I/O completion port, then an OVERLAPPED
structure needs to be deallocated when its I/O completes synchronously.
Otherwise, it needs to stay alive until a worker processes the notification from an I/O completion port.
This all sounds good until you realize that this only works if you manage the file handle yourself.
But if someone else gives you the file handle, how are you supposed to know when you should free the OVERLAPPED
structure? Is there any way to discover this after the fact?
Otherwise, does this basically imply you cannot correctly perform overlapped I/O on any file handle that you cannot guarantee the completion notification state of...?
Is there any way to discover this after the fact?
yes, exist - need use ZwQueryInformationFile
with FileIoCompletionNotificationInformation
FILE_IO_COMPLETION_NOTIFICATION_INFORMATION
is defined in wdm.h
so code which we need for query:
FILE_IO_COMPLETION_NOTIFICATION_INFORMATION ficni;
ZwQueryInformationFile(hFile, &iosb, &ficni, sizeof(ficni), FileIoCompletionNotificationInformation);
demo code for set and query
HANDLE hFile;
IO_STATUS_BLOCK iosb;
STATIC_OBJECT_ATTRIBUTES(oa, "\\systemroot\\notepad.exe");
if (0 <= ZwOpenFile(&hFile, FILE_GENERIC_READ, &oa, &iosb, FILE_SHARE_VALID_FLAGS, 0))
{
FILE_IO_COMPLETION_NOTIFICATION_INFORMATION ficni = { FILE_SKIP_COMPLETION_PORT_ON_SUCCESS };
if (0 <= ZwSetInformationFile(hFile, &iosb, &ficni, sizeof(ficni), FileIoCompletionNotificationInformation))
{
ficni.Flags = 0x12345678;
if (
0 > ZwQueryInformationFile(hFile, &iosb, &ficni, sizeof(ficni), FileIoCompletionNotificationInformation)
||
!(ficni.Flags & FILE_SKIP_COMPLETION_PORT_ON_SUCCESS)
)
{
__debugbreak();
}
}
ZwClose(hFile);
}
also let copy paste from wdm.h
(for not say that this is "undocumented" )
//
// Don't queue an entry to an associated completion port if returning success
// synchronously.
//
#define FILE_SKIP_COMPLETION_PORT_ON_SUCCESS 0x1
//
// Don't set the file handle event on IO completion.
//
#define FILE_SKIP_SET_EVENT_ON_HANDLE 0x2
//
// Don't set user supplied event on successful fast-path IO completion.
//
#define FILE_SKIP_SET_USER_EVENT_ON_FAST_IO 0x4
typedef struct _FILE_IO_COMPLETION_NOTIFICATION_INFORMATION {
ULONG Flags;
} FILE_IO_COMPLETION_NOTIFICATION_INFORMATION, *PFILE_IO_COMPLETION_NOTIFICATION_INFORMATION;
I have question - for what reason this is declared in wdm.h
?