Helium, MSDN Q105305
int hCrt;
FILE *hf;
AllocConsole();
hCrt = _open_osfhandle(
(long) GetStdHandle(STD_OUTPUT_HANDLE),
_O_TEXT
);
hf = _fdopen( hCrt, "w" );
*stdout = *hf;
i = setvbuf( stdout, NULL, _IONBF, 0 );
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.
Проблема в том, что CRT подхватывает значения хендлов потоков при инициализации, и далее уже не меняет. Поэтому надо ручками открывать потоки по хендлам и присваивать в глобальные переменные.