Is there a way to create stdio's FILE*
structure on the basis of a handle returned by WinAPI's CreateFile
in C++?
Asked
Active
Viewed 680 times
3

Serge Rogatch
- 13,865
- 7
- 86
- 158
-
Why would they be related in anyway? – Matthieu Brucher Jan 21 '19 at 10:15
-
@MatthieuBrucher , I know that at a minimum there is `_get_osfhandle()`: https://learn.microsoft.com/en-us/cpp/c-runtime-library/reference/get-osfhandle?view=vs-2017 . So the reverse is possible: get `HANDLE` from existing `FILE*` – Serge Rogatch Jan 21 '19 at 10:17
-
@MatthieuBrucher They *have* to be related. At the lowest level, a `FILE` *must* contain a `HANDLE` from `CreateFile`. (Actually, that's not quite true. It could use `NtCreateFile` - but that is vanishingly unlikely.) – Martin Bonner supports Monica Jan 21 '19 at 10:28
-
Why? You want to use `fprintf` with the open file? – i486 Jan 21 '19 at 10:28
-
@i486 , yes, I want to use stdio functions like `fscanf` and `fread`, get the stream buffering, etc. – Serge Rogatch Jan 21 '19 at 10:30
-
@SergeRogatch Instead of `fread` you can use `ReadFile`. `fscanf` is not good idea but if you need `*scanf` it can be combination from `ReadFile` and `sscanf`. Or simply use `_wfopen` to get `FILE *`. – i486 Jan 21 '19 at 10:35
-
@i486, I can't use `_wfopen` because I need to pass some platform-specific flags to `CreateFile` . – Serge Rogatch Jan 21 '19 at 10:40
1 Answers
7
Maybe like this:
#include <Windows.h>
#include <io.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <stddef.h>
// takes ownership of h_file
// caller is responsible for disposing of returned stream descriptor
[[nodiscard]] FILE *
make_stream(HANDLE const h_file)
{
FILE * p_file{};
int const fd{::_open_osfhandle(reinterpret_cast<::intptr_t>(h_file), _O_RDONLY)}; // transferring h_file ownerhip
if(-1 != fd)
{
p_file = ::_fdopen(fd, "r"); // transferring fd ownerhip
if(NULL != p_file)
{
// ok
}
else
{
if(-1 == ::_close(fd))
{
::abort();
}
}
}
else
{
if(FALSE == ::CloseHandle(h_file))
{
::abort();
}
}
return p_file;
}

user7860670
- 35,849
- 4
- 58
- 84