I'm engaged in what I hope is a learning experience for me in that I'm trying to create and use printf style console output statements in an AllocConsole() created console in a Windows GUI app. There is a problem with this and a work around to the problem from Microsoft. Below is a button press message handler from an sdk
style windows program I created to illustrate the issue, and below that is a brief description of the problem from Microsoft article...
Calling CRT Output Routines from a GUI Application
Article ID : 105305
Last Review : November 21, 2006
Revision : 4.2
long fnWndProc_OnCommand(lpWndEventArgs Wea) //This is code I extracted from an app I
{ //wrote to test the fix from Microsoft
unsigned int i;
int hCrt;
FILE *hf;
if(LOWORD(Wea->wParam)==IDC_BUTTON)
{
AllocConsole();
hCrt=_open_osfhandle((long)GetStdHandle(STD_OUTPUT_HANDLE),_O_TEXT);
hf = _fdopen( hCrt, "w" ); stdout = hf;
i = setvbuf( stdout, NULL, _IONBF, 0 );
printf("My Name Is Fred!\n");
MessageBox(Wea->hWnd,"Hopefully, You See A Console?","See A Console?",MB_ICONINFORMATION);
}
return 0;
}
below from Microsoft article...
This code opens up a new low-level CRT handle to the correct console output handle, associates a new stream
with that low-level handle, and replaces stdout with that new stream. This process takes care of functions
that use stdout, such as printf(), puts(), and so forth. Use the same procedure for stdin and stderr. Note
that this code does not correct problems with handles 0, 1, and 2. In fact, due to other complications, it
is not possible to correct this, and therefore it is necessary to use stream I/O instead of low-level I/O.
When a GUI application is started with the "start" command, the three standard OS handles STD_INPUT_HANDLE,
STD_OUTPUT_HANDLE, and 'STD_ERROR_HANDLE are all "zeroed out" by the console initialization routines. These
three handles are replaced by valid values when the GUI application calls AllocConsole(). Therefore, once
this is done, calling GetStdHandle() will always return valid handle values. The problem is that the CRT has
already completed initialization before your application gets a chance to call AllocConsole(); the three low
I/O handles 0, 1, and 2 have already been set up to use the original zeroed out OS handles, so all CRT I/O is
sent to invalid OS handles and CRT output does not appear in the console. Use the workaround described above
to eliminate this problem.
So what I'm saying here is that I've successfully implemented Microsoft's 'fix' and if the above message
handler is placed in a GUI program which has a IDC_BUTTON on the main form, the click of the button will
create a console and satisfactorily printf to it. What my problem is is that I don't understand how it
works! For what I'm really trying to do so as to increase my knowledge of programming is to convert this
technique to Bob Zale's PowerBASIC language, which is another programming language I use. So far I have
been able to successfully translate the first two of the three required lines over to PowerBASIC and get them
working, that is, the _open_osfhandle() function and the _fdopen() function in stdio.h, but I'm pretty
badly stuck on the stdout = hf statement. I have made some progress but my grasp of C seems to be failing
me. What I have accomplished is that I have successfully converted the FILE structure over to PowerBASIC
and I have that working. I am able to use PowerBASIC to open a file with fopen() and fprintf to it, then
close it with fclose(). I think that counts for something.
But where I'm stuck is best described by an excerpt from stdio below that shows some of the machinations
going on with _iobuf and FILE...
/
* The three standard file pointers provided by the run time library.
* NOTE: These will go to the bit-bucket silently in GUI applications! /
define STDIN_FILENO 0
define STDOUT_FILENO 1
define STDERR_FILENO 2
/
* The structure underlying the FILE type.
*
* Some believe that nobody in their right mind should make use of the
* internals of this structure. Provided by Pedro A. Aranda Gutiirrez
* <paag@tid.es>. /
typedef struct _iobuf
{
char _ptr;
int _cnt;
char _base;
int _flag;
int _file;
int _charbuf;
int _bufsiz;
char* _tmpfname;
} FILE;
/ The standard file handles /
extern FILE (_imp___iob)[]; / A pointer to an array of FILE */
define _iob (_imp___iob) / An array of FILE */
Like I said, I have managed to get the _iobuf (FILE) type created and working in PowerBASIC, but I don't understand what is going on with...
extern FILE (*_imp___iob)[];
Here is something else interesting from Microsoft's VC++ 6 stdio.h...
typedef struct _iobuf FILE;
ifndef _STDIO_DEFINED
_CRTIMP extern FILE _iob[];
endif / _STDIO_DEFINED /
define stdin (&_iob[0])
define stdout (&_iob[1])
define stderr (&_iob[2])
For me to translate this to another language I need to understand what is happening here and I don't. I guess my biggest quandry is where in the dickens is storage being declared and created for an array of FILE or _imp___iob[] structures? FILE seems to be defined here, yet there is an extern FILE _iob[] statement? Where is storage being provided for this structure or array of FILE structures? Not here! An extern to my understanding does not allocate storage? I guess the #define stdout (&_iob[1]) statement doesn't really put anything in this storage wherever its at, as its just a macro, but in the above message handler stdout = hf certainly does access memory!
I have searched every *.h file in the include directories of both VC++ 6 and Dev C++ for anything related to stdout or _iob but I can't find anything related to this, at least nothing that I can understand. I hope I've made clear the nature of my quandry and I hope someone here could be kind enough to shed some light on this issue for me, as I'm struggling mightily to understand it. As an aside, it was a post here several years ago by Clifford S showing me how to load the msvcrt.dll library with LoadLibrary() and GetProcAddress() to get the address of printf within that library that got me started in this interesting quest.
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
Just ran a utility program on msvcrt.dll that lists exported symbols and found that _iob[] (a struct of type FILE) is an exported symbol from that dll. So at least I'm making some progress.
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
Hello!
I'm engaged in what I hope is a learning experience for me in that I'm trying to create and use printf style console output statements in an AllocConsole() created console in a Windows GUI app. There is a problem with this and a work around to the problem from Microsoft. Below is a button press message handler from an sdk
style windows program I created to illustrate the issue, and below that is a brief description of the problem from Microsoft article...
Calling CRT Output Routines from a GUI Application
Article ID : 105305
Last Review : November 21, 2006
Revision : 4.2
http://support.microsoft.com/kb/105305
long fnWndProc_OnCommand(lpWndEventArgs Wea) //This is code I extracted from an app I
{ //wrote to test the fix from Microsoft
unsigned int i;
int hCrt;
FILE *hf;
if(LOWORD(Wea->wParam)==IDC_BUTTON)
{
AllocConsole();
hCrt=_open_osfhandle((long)GetStdHandle(STD_OUTPUT_HANDLE),_O_TEXT);
hf = _fdopen( hCrt, "w" );
stdout = hf;
i = setvbuf( stdout, NULL, _IONBF, 0 );
printf("My Name Is Fred!\n");
MessageBox(Wea->hWnd,"Hopefully, You See A Console?","See A Console?",MB_ICONINFORMATION);
}
return 0;
}
below from Microsoft article...
This code opens up a new low-level CRT handle to the correct console output handle, associates a new stream
with that low-level handle, and replaces stdout with that new stream. This process takes care of functions
that use stdout, such as printf(), puts(), and so forth. Use the same procedure for stdin and stderr. Note
that this code does not correct problems with handles 0, 1, and 2. In fact, due to other complications, it
is not possible to correct this, and therefore it is necessary to use stream I/O instead of low-level I/O.
When a GUI application is started with the "start" command, the three standard OS handles STD_INPUT_HANDLE,
STD_OUTPUT_HANDLE, and 'STD_ERROR_HANDLE are all "zeroed out" by the console initialization routines. These
three handles are replaced by valid values when the GUI application calls AllocConsole(). Therefore, once
this is done, calling GetStdHandle() will always return valid handle values. The problem is that the CRT has
already completed initialization before your application gets a chance to call AllocConsole(); the three low
I/O handles 0, 1, and 2 have already been set up to use the original zeroed out OS handles, so all CRT I/O is
sent to invalid OS handles and CRT output does not appear in the console. Use the workaround described above
to eliminate this problem.
So what I'm saying here is that I've successfully implemented Microsoft's 'fix' and if the above message
handler is placed in a GUI program which has a IDC_BUTTON on the main form, the click of the button will
create a console and satisfactorily printf to it. What my problem is is that I don't understand how it
works! For what I'm really trying to do so as to increase my knowledge of programming is to convert this
technique to Bob Zale's PowerBASIC language, which is another programming language I use. So far I have
been able to successfully translate the first two of the three required lines over to PowerBASIC and get them
working, that is, the _open_osfhandle() function and the _fdopen() function in stdio.h, but I'm pretty
badly stuck on the stdout = hf statement. I have made some progress but my grasp of C seems to be failing
me. What I have accomplished is that I have successfully converted the FILE structure over to PowerBASIC
and I have that working. I am able to use PowerBASIC to open a file with fopen() and fprintf to it, then
close it with fclose(). I think that counts for something.
But where I'm stuck is best described by an excerpt from stdio below that shows some of the machinations
going on with _iobuf and FILE...
/
* The three standard file pointers provided by the run time library.
* NOTE: These will go to the bit-bucket silently in GUI applications!
/
define STDIN_FILENO 0
define STDOUT_FILENO 1
define STDERR_FILENO 2
/
* The structure underlying the FILE type.
*
* Some believe that nobody in their right mind should make use of the
* internals of this structure. Provided by Pedro A. Aranda Gutiirrez
* <paag@tid.es>.
/
typedef struct _iobuf
{
char _ptr;
int _cnt;
char _base;
int _flag;
int _file;
int _charbuf;
int _bufsiz;
char* _tmpfname;
} FILE;
/ The standard file handles /
extern FILE (_imp___iob)[]; / A pointer to an array of FILE */
define _iob (_imp___iob) / An array of FILE */
Like I said, I have managed to get the _iobuf (FILE) type created and working in PowerBASIC, but I don't understand what is going on with...
extern FILE (*_imp___iob)[];
Here is something else interesting from Microsoft's VC++ 6 stdio.h...
typedef struct _iobuf FILE;
ifndef _STDIO_DEFINED
_CRTIMP extern FILE _iob[];
endif / _STDIO_DEFINED /
define stdin (&_iob[0])
define stdout (&_iob[1])
define stderr (&_iob[2])
For me to translate this to another language I need to understand what is happening here and I don't. I guess my biggest quandry is where in the dickens is storage being declared and created for an array of FILE or _imp___iob[] structures? FILE seems to be defined here, yet there is an extern FILE _iob[] statement? Where is storage being provided for this structure or array of FILE structures? Not here! An extern to my understanding does not allocate storage? I guess the #define stdout (&_iob[1]) statement doesn't really put anything in this storage wherever its at, as its just a macro, but in the above message handler stdout = hf certainly does access memory!
I have searched every *.h file in the include directories of both VC++ 6 and Dev C++ for anything related to stdout or _iob but I can't find anything related to this, at least nothing that I can understand. I hope I've made clear the nature of my quandry and I hope someone here could be kind enough to shed some light on this issue for me, as I'm struggling mightily to understand it. As an aside, it was a post here several years ago by Clifford S showing me how to load the msvcrt.dll library with LoadLibrary() and GetProcAddress() to get the address of printf within that library that got me started in this interesting quest.
Just ran a utility program on msvcrt.dll that lists exported symbols and found that _iob[] (a struct of type FILE) is an exported symbol from that dll. So at least I'm making some progress.