Disclaimer
I'm working on this essay. However, the information that is already here is sufficiently useful that I decided to post in, in spite of the fact that I've only covered a small part of handles. Over the next few months, I'll be enhancing it. So be patient; more is coming.
File Handles
I have a FILE *. Or I have a CFile or CStdioFile. What is its handle? And what handle is it?
There are several representations of handles for files at the application level. There are the file handles delivered by the C library, there are FILE * objects, and there are operating system file handles. They are all interchangeable, but only if you know what you are doing.
They are not necessarily interchangeable on an instant's notice, because of issues such as buffering. Thus if you reach into a FILE * and grab the underlying operating system handle and do a WriteFile, you will probably end up with a seriously corrupted file because there is buffered data being managed by the FILE * object. Therefore, unless you understand what needs to be done to flush buffers and maintain consistency in the various file handle images of the file contents and position, you are going to end up in serious trouble.
More typically, you have a fresh, newly-opened handle of one type and wish to now associate it with a representation more suitable for your task. For example, the C library function fopen does a pitiful job of handling file sharing, a concept which was nonexistent on the Unix operating system in which it was first specified. You want to use the full Win32 file sharing, but don't want to have to do raw WriteFile operations. And maybe you can't because you are retrofitting something into an existing, possibly portable-across-operating-systems source set, and you're writing the OS-specific module. So you can get a genuine Win32 HANDLE from CreateFile, and you want to associate it with a FILE * so you can now use it conveniently. Or even associate it with a C++ fstream. Keep reading!
C library "handles" are small integers that index into a table in the C runtime library. The C library has traditionally limited the number of simultaneously open files to some very restrictive number of handles, such as 16. This is no longer true in Win32. The C library in Win32 now supports up to 2048 low-level handles. The default is to allow a maximum of 512 FILE * objects, although you can easily change this limit up to the maximum of 2048 by calling _setmaxstdio.
If you don't see the transformation you need in the table below, you will need to use a combination of the transformations. For example, to transform a HANDLE to an fstream, you need to do something like
HANDLE h = ::CreateFile(...);
fstream f;
f.attach(_open_osfhandle(h));

<io.h>
int _open_osfhandle(long oshandle, int flags)
This takes a HANDLE value and returns a small integer that can be used to interface with the C library. The flags value includes O_APPEND, O_RDONLY, and O_TEXT. Note that this prototype assumes that a long and a HANDLE are the same size, and you will have to do a cast to get it past the compiler, for example
int h = _open_osfhandle((long) myhandle, 0);
It is not clear at this point to me what Microsoft will do in Win64 for this library call, because handles in Win64 (I think) will be 64 bits wide.
back to index
Given a C library file handle, you can convert it to a FILE* by calling the function _fdopen, passing in the C library file handle and getting in return a FILE *.
<stdio.h><code>
int _fdopen(int filehandle, const char * mode)
where mode is any of the mode values you can provide to fopen, such as "r", "rw", "w", etc.
back to index
Give a FILE * object, you can obtain the underlying C library handle by using _fileno
<stdio.h>
<code>int _fileno(FILE * f)
back to index
<io.h>
long _get_osfhandle(int filehandle)
This takes a C library file handle and returns the underlying Win32 HANDLE.
back to index
Underlying a CFile object is a system file handle. Sometimes. Maybe. In a raw CFile, the m_hfile member is a system file handle. However, Microsoft cautions that this may change in a derived class.
back to index
To associate a CFile object with an operating system file handle, you use the CFile constructor of the form
CFile::CFile(HANDLE h)
Whether you do this in a stack variable or use heap allocation depends on the nature of your application.
CFile file(myhandle);
or
CFile * file = new CFile(myhandle);
back to index
The m_pStream member of CStdioFile is the reference to the FILE * object that underlies it.
back to index
To associate a CStdioFile object with an operating system file handle, you use the CStdioFile constructor of the form
CStdioFile::CStdioFile(FILE * f)
Whether you do this in a stack variable or use heap allocation depends on the nature of your application.
<code>CStdioFile file(myfile);
or
CStdioFile * file = new CStdioFile(myfile);
back to index
If you need a handle to stdin, stdout, or stderr, without using the stdio.h library, you can use the API call GetStdHandle, specifying one of the constants, STD_INPUT_HANDLE, STD_OUTPUT_HANDLE, or STD_ERROR_HANDLE. These return a HANDLE value which can be used for ReadFile, WriteFile, or with any of the above.
back to index
If you have a C Library handle (the small integer from _open or _sopen) and need a C++ fstream-class object, take a look at the fstream constructor. One form takes a C file descriptor:
fstream(filedesc fd)
You can also use the fstream::attach method to attach a file descriptor to an existing fstream:
fstream f;
f.attach(fd);
For this to work, there must not be a file descriptor already attached to the fstream.
back to index
"fstream to C Library handle">fstream to C Library handle
To obtain the underlying C library handle from an fstream, use the .fd method
fstream f;
f.attach(fd)
ASSERT(fd == f.fd())
back to index
Inheritable handles
OK, someday soon...
Other Handles
Likewise...
| You must Sign In to use this message board. |
|
|
 |
|
 |
Hi!! How i can read now of row from my file..
code is
Cstring LooplistFile(myfile); CstdioFile LoopList;
if(Looplist.open(Looplistfile,Cfile::modeRead,&e)){
for (int i = 0; bla bla ;i++) {
do something.. }
but here what i can put insted of bla bla.. ie how i can find no of row..
Shah Satish
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
 |
Files don't have "rows", they have "lines". A "row" would apply to a concept like a listbox, a list control, or a grid.
Since you have not explained what is really in your file, it is hard to guess what you intended to do with it, or why i would be relevant.
I would be more inclined to do
...after opening the CStdioFile
CString line; while(Looplist.ReadString(line)) { /* read a line */ ... do something with line } /* read a line */
I'm not sure I see why a for loop is required, or what role 'i' would serve in this effort. If you want to store the lines in an array, CArray::Add could be used. If you want to add them to a CListBox, CListBox::AddString would be used. But your description of what you want to do is "do something", so you could do anything. But unless there is some compelling reason to need a counter, a for-loop is inappropriate.
If you need counter, just use counter++.
The reason you are having trouble filling in the condition of the loop is that a for loop with a condition does not appear to make any sense for this purpose.
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
 |
Hi, I have problem with ddk. When I include ntddk.h or other DDK headers I get hundreds of errors. What Should I do? please help me.
Every new thing you learn,Gives you a new personality.
|
| Sign In·View Thread·PermaLink | 2.00/5 |
|
|
|
 |
|
 |
Why are you including the DDK? What version of the DDK are you including? What kind of error messages?
It is impossible to respond to a description this vague.
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
 |
I am using winxp ddk too access video memory and modem memory
error C2011: '_FLOATING_SAVE_AREA' : 'struct' type redefinition
error C2011: '_FLOAT128' : 'struct' type redefinition
error C2011: '_CONTEXT' : 'struct' type redefinition
error C2011: '_LARGE_INTEGER' : 'union' type redefinition
error C2011: '_ULARGE_INTEGER' : 'union' type redefinition
error C2011: '_LUID' : 'struct' type redefinition
error C2084: function 'ULONGLONG Int64ShllMod32(ULONGLONG,DWORD)' already has a body
error C2084: function 'LONGLONG Int64ShraMod32(LONGLONG,DWORD)' already has a body
error C2084: function 'ULONGLONG Int64ShrlMod32(ULONGLONG,DWORD)' already has a body
error C2011: '_LIST_ENTRY' : 'struct' type redefinition
error C2011: '_SINGLE_LIST_ENTRY' : 'struct' type redefinition
error C2011: 'LIST_ENTRY32' : 'struct' type redefinition
error C2011: 'LIST_ENTRY64' : 'struct' type redefinition and more errors
Every new thing you learn,Gives you a new personality.
|
| Sign In·View Thread·PermaLink | 2.00/5 |
|
|
|
 |
|
 |
And please give the list of #include files showing where ntddk.h was included relative to other files.
Note that you can't access video memory or "modem memory" (whatever that is!) from user space. So are you writing a device driver?
|
| Sign In·View Thread·PermaLink | 5.00/5 |
|
|
|
 |
|
 |
Hi, I have allot off old functions that using FILE* as passing parameter. Now I use a Compound Doc that use IStream interface... How to convert IStream to FILE * ? Thank's
|
| Sign In·View Thread·PermaLink | 1.50/5 |
|
|
|
 |
|
 |
I found the article usefull. However, the new version of the standard library does not allow to make a stream from a handle any more. The function fstream::attach and the friends are not available anymore. However, there still exists an fstream constructor that takes FILE. So, one can still create an fstream from handle in two steps
int theFd = _open_osfhandle(INT_PTR(theHandle), O_RDONLY); FILE* theFile = _fdopen(theFd, "r"); ifstream* theStream = new ifstream(theFile); It took me some time and frustration to realize how to do it with the new library. Hope, it will helps someones time.
Artem Alimarine
|
| Sign In·View Thread·PermaLink | 5.00/5 |
|
|
|
 |
|
 |
Hi!
If I have a fd and wants to convert it to a handle? (I have a fd and wants to call DeviceIoControl....)
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
 |
What's an 'fd'? There are C library handles (small integers), FILE * objects, etc., but I have no idea what you mean by 'fd'.
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
 |
|
|
 |
|
 |
See KB99173 for details. Windows discourages the use of _get_osfhandle for converting between file descriptors and HANDLE types.
|
| Sign In·View Thread·PermaLink | 1.00/5 |
|
|
|
 |
|
 |
Interesting. What is odd is that no explanation of the "problems" is given. For example, if there is I/O going on through the C library handle, and reading or writing is done via the HANDLE, it is clear that the buffering issues will result in a skew of some sort in the data stream. But if the handles are merely translated before any I/O takes place, they should work OK. I've looked at the code and it is pretty trivial. I think it would have been a more informative document if it had not been so handwaving.
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
 |
Hi Joseph, great article! Thanks!
I was just wondering if I could get some "fake" handle from the OS.
Let me explain my problem. Actually, I have an application that writes data to a log file. I don't have the source code of this application and I needed to have the log information written in a SQL Server table.
The first thought was to read the text file and write to SQL Server, but It doesn't works well...
So I did a hook at the "CreateFile", "WriteFile" and "CloseHandle" APIs for this application.
When the application calls the CreateFile API, I check the name of the file, and if the name is "Log.txt" I just return "555" as a "valid" handle and the file isn't created. When the application calls WriteFile, I write in the SQL Server table and returns TRUE. And finnaly, when the application calls CloseHandle with the "555" handle, I just return TRUE.
The application is working perfectly, and doing exactly what I needed. I just wanted to make the things even more perfect. The application also keep some other files opened, so some day, the handle "555" could be in use for other opened file and this would cause some crash as the Log routine will write the information to some other opened file.
I just wanted to "reserve" some file Handle with the OS, so no other application could take this "reserved handle", but I don't want to create any file. Is It possible? Do yoy have any suggestion?
Best Regards,
Caio Proiete  MCSD (Visual C++) - MCP (SQL Server 2000)
|
| Sign In·View Thread·PermaLink | 2.00/5 |
|
|
|
 |
|
 |
My first thought is to allow CreateFile to create the file and use that handle instead of 555. You do not have to write anything to the file with WriteFile but you should close it with CloseHandle.
John
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
 |
Hi John, thank you for your comments.
Yep... I already thought about it and till now It's the only (safe) solution. 
I think I'll create the file in the machine's Temp folder just to hide the file from the application's folder.
Thanks anyway. Best Regards,
Caio Proiete  MCSD (Visual C++) - MCP (SQL Server 2000)
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
 |
Caio Proiete wrote: I think I'll create the file in the machine's Temp folder just to hide the file from the application's folder.
That is what I would do. You might want to look into generating a unique filename so you don't run into problems if the file exists in that directory...
John
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
 |
This approach is bizarre, and I'm amazed it can be made to work at all. It strikes me as extremely fragile. The need to hook the APIs is definitely over the top as far as a piece of production code is concerned. The fact that the filename is hardwired is off-the-wall. This is very risky code.
There is no possiblity of reserving the file handle. The concept does not exist. You are on very thin ice here.
I would be inclined to use a named pipe, and if you have to do an intercept, change the name from "log.txt" to "\\.\pipe\log-pipe-name-here" and then not bother with any other intercepts. Then have your app read from the named pipe and write to the SQL database.
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
 |
Hi Joseph! I guess I know what you are thinking and NO... this is not bizzare as It looks . You'll agree with me.
The software is working like a charm and It is in production for some months without any problem...
Let me explain more about the problem I had and the (best) solution I've found:
I have a program "A" that was developed by third-party and I don't have the source code. This program "A" is used to control the access to the building... when an employee pass the magnetic card on an device, this device send the "employee card ID" to a machine through serial port. The program "A" keeps listening the serial port and when a message arives, it saves this message in a text file into the machine and opens the door if the employee have is authorized. The file path is kind of hard-coded because it's "C:\AppFolder\DB\Log.txt". I repeat: I don't have the source-code of this program "A".
The problem: ------------ All messages written in the text file was needed to be imported to a SQL Server table at real-time. The program "A" opens the file "Log.txt" exclusively so I couldn't open the file until the program "A" was closed.
The solution I've found: ------------------------ After some API-spying I realized that the program "A" calls CreateFile API to create the "Log.txt" file, calls WriteFile API to write the messages came from serial port into the file and when the program is closed, it calls CloseHandle API to close the file handle.
My first thought was create a hook at this APIs so I could receive the messages from WriteFile and then write the messages in the SQL Server table... I didn't know how could I hook this APIs so I asked this at many forums and everybody said that I needed to create a device driver and I didn't accepted that... So after thinking a lot, I had an idea: Well.. all the APIs I needed are stored in KERNEL32.DLL, so I've created a DLL to act as a "proxy" for KERNEL32.DLL. I've implemented only the functions I needed on this DLL (CreateFile, WriteFile and CloseHandle) and the other 800+ functions I just redirected to KERNEL32.DLL original function.
I've put MYKERNEL.DLL into the program "A" folder, opened the EXE file of the program "A" in a hexadecimal editor, and replaced all the calls for KERNEL32.DLL to MYKERNEL.DLL!
Everything solved... when the application starts it uses MYKERNEL.DLL as a proxy for KERNEL32.DLL and when the program "A" calls the WriteFile, I just write the information in a SQL Server table and returns true (without writing to the text file)... 
My question about getting the "fake" handle was because I wanted to avoid the creation of an empty file... but I saw that It's impossible to reserve some handle... but that's OK. The file is there... empty...
Hope this have cleared the things for you! Do you have any better idea to solve this problem?? I'd love to hear!! (and soon because I'm writting an article for CodeProject explain this kind of hook! )
Best Wishes,
Caio Proiete  MCSD (Visual C++)
|
| Sign In·View Thread·PermaLink | 5.00/5 |
|
|
|
 |
|
 |
A great solution to a complicated problem! Sometimes all you need is a little creativity, don't let anyone tell you it's impossible.
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
 |
Hi, Thanks very much for your quick answer, But… I tried it and I have some difficult in it: 1- I tried to define the structs as you said, but I have UNICODE_STRING witch not defined in winnt , so I should include ntddk.h as you said. BUT when I include it I get many error like : 'MAX_NATURAL_ALIGNMENT' : macro redefinition , it’s a conflict between the definition in ntdef.h & winnt.h So I make no include and I get the definition of the UNICODE_STRING from ntdef.h and I put it in my code. And the first problem OK, but do you have any explanation ? I’m using MFC Appwiz 2- after solving the first problem, I have another one : unresolved external symbol "long __cdecl ZwQueryObject(void *,enum _OBJECT_INFORMATION_CLASS,void *,unsigned long,unsigned long *)" (?ZwQueryObject@@YAJPAXW4_OBJECT_INFORMATION_CLASS@@0KPAK@Z) As you see the link failed in finding the symbol of the function ZwQueryObject ! I’m defining it in my code as : typedef LONG NTSTATUS;
NTSTATUS ZwQueryObject(HANDLE handle,_OBJECT_INFORMATION_CLASS obinfoclass,PVOID obinfo,ULONG obinfolength,PULONG returnlength );
And I put the ntdll.lib in my optional modules in the link tab in the setting Dialog box. I’m using the E:\NTDDK\libchk\i386\ntdll.lib Any idea ? Thanks a lot. Fadi 
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
 |
There is a trick to including ntddk.h, which doesn't work with the latest ntddk.h.
From Nebbet's book:
namespace NT { extern "C" { #pragma warning(disable:4005) #include #pragma warning(default:4005) } } using NT:NTSTATUS;
The reason your extern is not found is you failed to include it in an extern "C" { } context, so the compiler converted the name to a C++ name.
|
| Sign In·View Thread·PermaLink | 2.00/5 |
|
|
|
 |
|
 |
Hi Thnaks for the answer, but i still have some dificulties...
What do you mean by this : namespace NT { extern "C" { #pragma warning(disable:4005) #include #pragma warning(default:4005) } } using NT:NTSTATUS; Should I put the "ntddk.h" after #include or not? And when I used the extern "c"{} I still have unresolver external symbol, but without arguments. I'm using the ntdll.lib from the ddk 2195 is this a problem?
Please could you send me a smale project with teh lib & dll file, to my email bfadi@netcourrier.com Thanks again

|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
 |
|
|