3
votes

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

1
Why would they be related in anyway? - Matthieu Brucher
@MatthieuBrucher , I know that at a minimum there is _get_osfhandle(): docs.microsoft.com/en-us/cpp/c-runtime-library/reference/… . So the reverse is possible: get HANDLE from existing FILE* - Serge Rogatch
@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
Why? You want to use fprintf with the open file? - i486
@i486 , yes, I want to use stdio functions like fscanf and fread, get the stream buffering, etc. - Serge Rogatch

1 Answers

7
votes

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;
}