How do I get the file HANDLE from the fopen FILE structure?
Asked Answered
C

3

38

The fopen function returns a pointer to a FILE structure, which should be considered an opaque value, without dealing with its content or meaning.

On Windows, the C runtime is a wrapper of the Windows API, and the fopen function relies on the CreateFile function. The CreateFile function returns a HANDLE, which is used by other Windows API.

Now, I need to use Windows API deep inside of a library that uses fopen and FILE*. So: is there a way to get the HANDLE from the FILE structure? As this is compiler specific, I mean on the MSVC runtime library.

I understand that this would be an ugly, non-portable hack, and that could broke if Microsoft changes the internal format of FILE... but I'm developing on a closed system (i.e. on a Windows CE embedded system) and refactoring the library would be difficult and time consuming.

Calefaction answered 21/10, 2010 at 16:11 Comment(1)
Great question, I dealt with this one myself over 2 years ago.Costive
S
23

Use _fileno followed by _get_osfhandle. Don't forget to _close it when you are done.

EDIT: it's not clear to me that _get_osfhandle is supported on WinCE. However the docs for WinCE _fileno say it returns a "file handle" rather than "descriptor". YMMV but this suggests that you can maybe just use _fileno return value directly as a handle on WinCE.

EDIT: #2 That theory is supported by this person's experience.

"If you take a look at the header files that I posted to the list on Jan 29 you can see how I handled the file creation/handle problem. I didn't have to replace all FILE* items with HANDLEs. See the following snippet from fileio.cpp:

#ifndef q4_WCE

  FlushFileBuffers((HANDLE) _get_osfhandle(_fileno(_file)));
  HANDLE h = ::CreateFileMapping((HANDLE)
_get_osfhandle(_fileno(_file)),
                        0, PAGE_READONLY, 0, len, 0);
#else

  FlushFileBuffers((HANDLE) _fileno(_file));
  HANDLE h = ::CreateFileMapping((HANDLE) _fileno(_file),
                    0, PAGE_READONLY, 0, len, 0);
#endif //q4_WCE

It turns out that _fileno returns a handle. You just have to cast it."

Skyscraper answered 21/10, 2010 at 16:44 Comment(1)
Thank you, _fileno was good enough for my Windows CE issue, but your answer seems actually "portable" on all the MS platforms with any version of MSVC.Calefaction
I
7

On Linux, there's the int fileno(FILE *); function that returns the file descriptor (the one that was returned by the low-level open function) from the FILE*.

I don't know if it applies to Windows and returns the HANDLE though?

Igenia answered 21/10, 2010 at 16:18 Comment(2)
Hmm, that's possible: msdn.microsoft.com/en-us/library/ee479262.aspx states that "_fileno gets file handle associated with stream". At least on Windows CE it should work.Calefaction
It is just a compat function for *nix. Handles are pointer sized, 8 bytes on Win64.Sylvan
W
5

For C, try this

HANDLE foo = (HANDLE)_get_osfhandle(fileno(fopen("bar.txt", "w")));
Wintery answered 30/7, 2012 at 5:13 Comment(1)
Used later, this is telling me the handle is invalid for e.g. stdout.Korn

© 2022 - 2024 — McMap. All rights reserved.