I want to change the completion key for a handle that has been added to an I/O completion port. There are multiple answers like this that state that it can be done via NtSetInformationFile, but is there a user space equivalent for that? I am not very fond of the though of loading that function dynamically from ntdll.dll
.
Asked
Active
Viewed 307 times
0

Rudolfs Bundulis
- 11,636
- 6
- 33
- 71
-
the *NtSetInformationFile* is user space api too (it is both user and kernel mode api - exist in both). and you not need - *loading that function dynamically from ntdll.dll*. can, but not must. you can import this api like any another win32 api - simply add *ntdll.lib* or *ntdllp.lib* to linker input. this api exist how minimum from win2000 (faster of all it exist in nt4 too) and unchanged all this time. and absolute sure - will be exported always. another task - from my experience - change the completion key for a handle - not best and good solution in most case. and not always possible – RbMm Mar 21 '21 at 20:45
-
Are you looking for SetFileInformationByHandle https://learn.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-setfileinformationbyhandle ? – Simon Mourier Mar 22 '21 at 06:39
-
@SimonMourier despite *SetFileInformationByHandle* shell over *NtSetInformationFile*, problem here in *FILE_INFO_BY_HANDLE_CLASS* - it not mapped surjective to *FILE_INFORMATION_CLASS*. *FileReplaceCompletionInformation* not mapped from *FILE_INFO_BY_HANDLE_CLASS* or how minimum not documented. i not view nothing bad in direct call *NtSetInformationFile*, but have some doubt - are this ( change the completion key ) really need and good solution – RbMm Mar 22 '21 at 08:54
-
@RbMm but when you say it exists in user space, there are no headers in Windows SDK (only WDK) that expose the needed structures. Of course I can forcefully add the headers, but then can that really be called a true user space usage? `ntifs.h` and others for me reside only in the wdk provided `km` include folder. As for the "bad" part - i need to mimic epoll/kqeue so this seems the best way to do that, instead of keeping the context pointer in an extended overlapped structure. – Rudolfs Bundulis Mar 22 '21 at 09:29
-
@SimonMourier thanks for the tip, as stated by @RbMm there does not seem to be a clear mapping for the `FileReplaceCompletionInformation` which I need to set the completion key. – Rudolfs Bundulis Mar 22 '21 at 09:32
-
Indeed, not all operations are mapped back to SetFileInformationByHandle. – Simon Mourier Mar 22 '21 at 09:34
-
this is "true" user space api. no any fundamental difference between say *SetFileInformationByHandle* and *NtSetInformationFile*. this api always was exported and will be exported by *ntdll.dll*. about header files - yes, bit problematic use *ntifs.h* with *windows.h* at once, especially with */permissive-* compiler option. but anyway possible (i do this). also possible copy-paste separate function definition or use headers from process hacker github. but main problem in the functional plane. – RbMm Mar 22 '21 at 09:38
-
1for me still unclear what you try to do ( "mimic epoll/kqeue"). if you ask question about real problem, possible more detail answer – RbMm Mar 22 '21 at 09:38
-
@RbMm ok, then at least we came to the same point of understanding on how to use it. Is is accesiible for user space, but headers are not there, so I need to copy the needed definitions and link it in. Thanks, I simply though maybe there are some macros which are needed to enable the definition of that function in Windows SDK but apparently not. As for the usage part - you seem to stress that is is bad, but can you provide an example of what can go wrong? Other answers on SO state that it simply changes the completion key, which is an opaque pointer in kernel space, seems quite trivial. – Rudolfs Bundulis Mar 22 '21 at 09:45
-
in [`FILE_OBJECT`](https://learn.microsoft.com/en-us/windows-hardware/drivers/ddi/wdm/ns-wdm-_file_object) exist pointer to [`IO_COMPLETION_CONTEXT`](https://www.nirsoft.net/kernel_struct/vista/IO_COMPLETION_CONTEXT.html) and by use *FileReplaceCompletionInformation* possible if no active I/O on file, replace *Key* here. but i simply not sure for what/when this is useful. despite very wide use iocp in self code – RbMm Mar 22 '21 at 09:51
-
simply question - for what need **change** this key. when and in what situation this can be need. and not always this is possible. *FileReplaceCompletionInformation* can fail – RbMm Mar 22 '21 at 09:57
-
@RbMm I do not want to have the completion handling context information in the extended overlapped classes, thus when a handler for a socket changes, I want to transparently change the key so I can just move the sockets to a different handler. Yes, I would not do this in a Windows only IOCP app and yes, I see how pending I/O notifications (or worse, already propogated to user space with the old completion key) is an issue, I am designing the flow, so that when this happens there is a guarantee of no pending iocp requests on that handle. – Rudolfs Bundulis Mar 22 '21 at 10:02
-
we have 2 context pointers in I/O request - *Key* and *ApcContext* - the *Key* about which you ask now, usually is permanent and per file(socket) it set once. the *ApcContext* is per I/O operation, so every I/O can have self context. in win32 layer the pointer to `OVERLAPPED` used in place *ApcContext*. and how you know -- you can extend (inherit from) `OVERLAPPED` to hold here pointer to class object, which represent file. i not view for what need change *Key*. of course all this windows only. can not say how this can be ported to another system – RbMm Mar 22 '21 at 10:15
-
@RbMm yep, I totally agreed with your description. Since other systems do not have a requirement for an overlapped thingy (which I have yes, extended to signal if the operation is read/write and keep the pinned buffer pointer(s)), I do not want to put the context there, since on other platforms it lives elsewehere. Maybe I will redesign it , but at least I'll give a shot to changing the key and see how it works out. Thanks. – Rudolfs Bundulis Mar 22 '21 at 10:19