How to do non-buffered writes to stdout? - windows

I need 20 'H' characters to appear at 1 second intervals. This program displays nothing till the end
use std::io::Write;
use std::time::Duration;
fn main() {
let ch = 'H' as u8;
for _ in 0..20 {
let buff = vec![ch];
std::io::stdout().write(&buff).unwrap();
std::io::stdout().flush().unwrap();
std::thread::sleep(Duration::from_millis(1000));
}
}
This equivalent C++ program works fine
#include <iostream>
#include <Windows.h>
int main()
{
for(int i = 0; i < 20; i++)
{
std::cout << (char)'H';
std::cout.flush();
Sleep(1000);
}
}
I tried crossterm and could not make that work but it looks really interesting. I tried crossterm_winapi which has direct calls to WriteConsoleW in it, but then I got no output at all.

I am going to answer my own question because I went through a lot of discovery here and I am sure other will find it useful.
BTW - the original question got derailed in the comments section explaining why my c++ equivalent (without flush) worked / didnt work / shouldnt work / might work. Lets ignore that - I added flush.
Firstly Debuggers
vscode and Vs2019 do stuff with stdout in order to try to be helpful. Most of the time it is helpful but not in this case
vscode steals stdout to make it appear in the terminal window. Normally this would be directed to a console window. It also imposes its own buffering regardless of what you do with flushing etc.
The real end for my rust code is a c# gui application calling the rust code as a cdylib. Originally this dll was written in c++. When running a GUI app vs2019 also steals stdout (not the case for console apps, nothing to do with my mini c++ code above) so that it can display it the 'output' window.
Both these behaviors disappear if the app is run outside the debugger of course. But that makes debugging tough.
This of course confused a lot of my investigation because I was not seeing output in various cases because I was looking in the wrong place.
Solution 1
The original code in my question actually works fine if you run it via cargo run from a console window. Excellent. vscode buffers it all up if ran from inside it - so dont do that.
Problem 2, no console window
Windows gui app launch 'knows' that this program doesnt need a console window so stdout is piped to a bitbucket. I had the same issue in the c# -> c++ version. The secret here is to create a console window and reattach stdout to it.
solution 2
Reaches for winapi crate.
unsafe {
let ff = winapi::um::wincon::FreeConsole();
let ret = winapi::um::consoleapi::AllocConsole();
let err = winapi::um::errhandlingapi::GetLastError();
};
FreeConsole just to detach if we are connected to something weird. Then AllocConsole creates a console window and connects the process to it, not wired up to anything yet though. So now wire the new console window to stdout:
let file = OpenOptions::new().write(true).read(true).open("CONOUT$").unwrap();
unsafe{
let err = winapi::um::processenv::SetStdHandle(winapi::um::winbase::STD_OUTPUT_HANDLE, file.as_raw_handle());
}
CONOUT$ is special name for the output buffer of the connected console window. SetStdHandle connects it to stdout.
Now a new window pops up next to the gui and all stdout writes appear there - whoo hoo.
This also works for vscode debugging. A new 'dos' window appears and the stdout appears there. An added bonus
Problem 3 need lower level access
In my original PDP engine in c++ I was not happy still using std::cout, I needed to get as close the the windows console subsystem as possible (I am emulating the behavior of a raw physical device for the PDP). So I decided to use direct windows IO in this new version
Solution 3
So still AllocConsole and open CONOUT$ but call the Console write directly
let buff: [u8; 1] = [ch];
let ptr: *const c_void = buff.as_ptr() as *const _ as *const c_void;
let mut cells_written: u32 = 0;
// write to console
unsafe {
WriteConsoleA(
file.as_raw_handle(),
ptr,
1,
&mut cells_written,
NULL,
) ;
};
file is the handle return by open of CONOUT$
Works nicely. I know I will need to do the same for stdin / CONIN$ at some point

Related

How to simulate a TTY while also piping stdio?

I'm looking for a cross-platform solution for simulating a TTY (PTY?) in Rust while also piping stdio.
The frontend is based on web technologies where an interactive terminal is shown. Users can run commands and all their inputs will be sent to the Rust backend, where the commands get executed. Std{in,out,err} are sent back end forth to allow for an interactive experience.
Here's a simplified example (piping only stdout):
let mut child = Command::new(command)
.stdout(Stdio::piped())
.spawn()
.expect("Command failed to start");
loop {
let read = reader.read(&mut chunk);
if let Ok(len) = read {
if len == 0 {
break;
}
let chunk = &chunk[..len];
send_chunk(chunk); // send chunk to frontend
} else {
eprintln!("Err: {}", read.unwrap_err());
}
}
Currently, running the command tty prints: not a tty, but ideally, it should output a file name (e.g /dev/ttys002). And programs, such as atty should return true.
Running only the backend in a terminal, with stdio inherited works, but then I can't send the stdio back to the frontend.
Define "cross platform". As far as PTYs is concerned, those are pseudo devices supported by the kernel, complete with ioctls and everything. As a matter of fact a lot of the things your terminal emulator will have to do, is implementing the receiving end of those ioctls.
As long as you're on a machine with the BSD API (which includes Linux), the best course of action would be to openpty and roll with that. If you want to be portable to non BSD PTY capable systems, you'll have to hook the tty functions in the child process (by preloading a helper library).

Using stdout in a Win32 GUI application: crashes if I don't have a redirect to file in arguments

I'm building a Win32 GUI app. Inside that app, I'm using a DLL that was intended to be used in a command line app.
Suppose Foo.exe is my GUI app, and bar() is a function in the DLL that prints "hello" to stdout. Foo.exe calls bar().
If I run Foo.exe from the command line with a redirect (>) (i.e. Foo.exe > out.txt) it writes "hello" to out.txt and exits normally (as expected).
However, if I run Foo.exe without a redirect (either from cmd.exe or by double-clicking in Windows Explorer), it crashes when bar() is called.
If I run Foo.exe inside the debugger with the redirect in the command line (set through VS's properties for the project) and call "GetStdHandle(STD_OUTPUT_HANDLE)", I get a reasonable address for a handle. If I call it without the redirect in the command line, I get 0.
Do I need something to "initialize" standard out? Is there a way that I can set up this redirect in the application startup? (Redirecting to a file would be ideal. But just throwing out the data printed by the DLL would be okay, too.)
Finally, I suspect that the DLL is writing to stdout through the CRT POSIX-like API, because it is a cross-platform DLL. I don't know if this matters.
I've tried creating a file with CreateFile and calling SetStdHandle, but that doesn't seem to work. I may be creating the file incorrectly, however. See code below.
HANDLE hStdOut = GetStdHandle(STD_OUTPUT_HANDLE);
// hStdOut is zero
HANDLE hFile;
hFile = CreateFile(TEXT("something.txt"), // name of the write
GENERIC_WRITE, // open for writing
0, // do not share
NULL, // default security
CREATE_NEW, // create new file only
FILE_ATTRIBUTE_NORMAL, // normal file
NULL); // no attr. template
BOOL r = SetStdHandle(STD_OUTPUT_HANDLE, hFile) ;
hStdOut = GetStdHandle(STD_OUTPUT_HANDLE);
// hStdOut is now equal to hFile, and r is 1
bar();
// crashes if there isn't a redirect in the program arguments
UPDATE: I just found this article: http://support.microsoft.com/kb/105305. It states "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."
My DLL definitely uses file handles 0,1 and 2. So, there may be no good solution to this problem.
I'm working on a solution that checks for this case, and re-launches the exe appropriately using CreateProcess. I'll post here when I'm done.
The solution that I've found is the following:
obtain a valid File HANDLE in some way to direct the standard output.
Lets call the file handle "fh".
(please note that on Windows a File HANDLE is not the same thing of a file descriptor)
associate a file descriptor to the file handle with _open_osfhandle
(see http://msdn.microsoft.com/en-us/library/kdfaxaay.aspx for details)
Lets call "fd" the new file descriptor, an int value.
call dup2 to associate the STDOUT_FILENO to the given file descriptor:
dup2(fd, STDOUT_FILENO)
create a file strem associated to the stdout file descriptor
FILE* f = _fdopen(STDOUT_FILENO, "w");
memset stdout to the content of f:
*stdout = *f
call SetStdHandle on the given file handle:
SetStdHandle(STD_OUTPUT_HANDLE, ofh);
Please note that I've not tested exactly this sequence but something slightly different.
I don't know if some steps are redundant.
In any case the following article explain very well the concept of file handle, descriptor et fiel stream:
http://dslweb.nwnexus.com/~ast/dload/guicon.htm
You must build foo.exe as a console application with the /SUBSYSTEM switch. Windows will allocate a console (stdout) for your application automatically, which can be :
The current console
A redirection to a file
A pipe to another program's STDIN
If you build foo.exe as a GUI application, the console is not allocated by default, wich explains the crash
If you must use the GUI subsystem, it can still be done with AllocConsole. This old WDJ article has sample code to help you.
Can you tell me which library do you use? This problem have good solution. Write small stub launcher EXE (in GUI mode but with NO windows!) that have your icon and that all shortcuts launch. Make this stub EXE "CreateProcess" the real EXE with redirected output to "NUL" or "CON", or, CreateProcess() it suspended, take its STDOUT, doing nothing with it. This way, your original EXE should work without visible console, but will actually have where to write - in the handles 0,1 and 2 that are taken by the parent invisible stub EXE. Note that killing the parent EXE may make the child lost its handles - and - crash.
You may end up with two processes in Task Manager. So you can try making these 2 processes a job like Google Chrome does.
On your question Do I need something to "initialize" standard out? - only your parent / launcher can pre-initialize your STDOUT for handles 0,1 and 2 "properly".

SetWindowsHook Global not very Global

I'm playing around with SetWindowsHookEx, specifically I would like be able to find out about any window (on my desktop) thats been activated, via mouse or keyboard.
Reading through MSDN docs for SetWindowsHookEx it would appear that a WH_CBT type would do the job. I've created a dll and put all the code in there, which I control from a gui app (which also handles the unhook).
BUT I only appear to be getting the activation code when I activate my gui app though, any other app I activate is ignored.
In my dll I have the setup code and the CBTProc like so:
LRESULT WINAPI CBTProc(int Code, WPARAM W, LPARAM L) {
if(Code<0) CallN....
if (Code == HCBT_ACTIVATE) { // never get unless I activate my app
HWND a = reinterpret_cast<HWND>(W);
TRACE("this window was activated %d\n", a);
}
CallNext....
}
EXPORTED HHOOK WINAPI Setup(HWND MyWind) {
...
// gDllUInstance set in dllmain
return SetWindowsHookEx(WH_CBT, CBTProc, gDllUInstance, 0);
}
All pretty simple stuff, i've tried moving the setup out of the dll but I still get the same effect.
It would appear that the dll is getting loaded into other processes, I'm counting the number of DLL_PROCESS_ATTACHs I'm getting and can see its going up (not very scientific i know.
NOTE that this is 32 bit code running on 32bit OS - win2k3.
Are my expectations of the hooking mechanism wrong? should I only be getting the activation of my app or do I need a different type of hook?
EDIT: the trace function writes to a file telling me whats sending me activations
TIA.
Turns out its working ok, as Hans points out, i'm just not seeing the output from the debugger from the other processes, if I put in some extra tracing code - one trace file per attached process - I can see can see that things are working after all.
Many thanks for the replies.

Win32: How to crash?

i'm trying to figure out where Windows Error Reports are saved; i hit Send on some earlier today, but i forgot that i want to "view the details" so i can examine the memory minidumps.
But i cannot find where they are stored (and google doesn't know).
So i want to write a dummy application that will crash, show the WER dialog, let me click "view the details" so i can get to the folder where the dumps are saved.
How can i crash on Windows?
Edit: The reason i ask is because i've tried overflowing the stack, and floating point dividing by zero. Stack Overflow makes the app vanish, but no WER dialog popped up. Floating point division by zero results in +INF, but no exception, and no crash.
You guys are all so verbose! :-)
Here's a compact way to do it:
*((int*)0)=0;
Should be a good start:
int main(int argc, char* argv[])
{
char *pointer = NULL;
printf("crash please %s", *pointer);
return 0;
}
You are assuming the memory dumps are still around. Once they are sent, AFAIK the dumps are deleted from the machine.
The dumps themselves should be located in %TEMP% somewhere.
As far as crashing, that's not difficult, just do something that causes a segfault.
void crash(void)
{
char* a = 0;
*a = 0;
}
Not sure if this will trigger the Error Reporting dialog, but you could try division by zero.
The officially-supported ways to trigger a crash on purpose can be found here:
http://msdn.microsoft.com/en-us/library/ff545484(v=VS.85).aspx
Basically:
With USB keyboards, you must enable
the keyboard-initiated crash in the
registry. In the registry key
HKEY_LOCAL_MACHINE\System\CurrentControlSet\Services\kbdhid\Parameters,
create a value named
CrashOnCtrlScroll, and set it equal to
a REG_DWORD value of 0x01.
Then:
You must restart the system for these
settings to take effect.
After this is completed, the keyboard
crash can be initiated by using the
following hotkey sequence: Hold down
the rightmost CTRL key, and press the
SCROLL LOCK key twice.
No programming necessary ;) No wheel reinvention here :)
Interesting to know how to crash Windows. But why not have a look at
%allusersprofile%\Application Data\Microsoft\Dr Watson\
first? Look out for application specific crashdata folders as well, I found e.g.
...\FirefoxPortable\Data\profile\minidumps\
and
...\OpenOfficePortable\Data\settings\user\crashdata\.

Change default Console I/O functions handle

Is it possible to somehow change standart I/O functions handle on Windows? Language preffered is C++. If I understand it right, by selecting console project, compiler just pre-allocate console for you, and operates all standart I/O functions to work with its handle. So, what I want to do is to let one Console app actually write into another app Console buffer. I though that I could get first´s Console handle, than pass it to second app by a file (I don´t know much about interprocess comunication, and this seems easy) and than somehow use for example prinf with the first app handle. Can this be done? I know how to get console handle, but I have no idea how to redirect printf to that handle. Its just study-purpose project to more understand of OS work behind this. I am interested in how printf knows what Console it is assiciated with.
If I understand you correctly, it sounds like you want the Windows API function AttachConsole(pid), which attaches the current process to the console owned by the process whose PID is pid.
If I understand you correct you can find the source code of application which you want to write in http://msdn.microsoft.com/en-us/library/ms682499%28VS.85%29.aspx. This example show how to write in stdin of another application and read it's stdout.
For general understanding. Compiler don't "pre-allocate console for you". Compiler use standard C/C++ libraries which write in the output. So if you use for example printf() the following code will be executed at the end will look like:
void Output (PCWSTR pszwText, UINT uTextLenght) // uTextLenght is Lenght in charakters
{
DWORD n;
UINT uCodePage = GetOEMCP(); // CP_OEMCP, CP_THREAD_ACP, CP_ACP
PSTR pszText = _alloca (uTextLenght);
// in the console are typically not used UNICODE, so
if (WideCharToMultiByte (uCodePage, 0, pszwText, uTextLenght,
pszText, uTextLenght, NULL, NULL) != (int)uTextLenght)
return;
WriteFile (GetStdHandle (STD_OUTPUT_HANDLE), pszText, uTextLenght, &n, NULL);
//_tprintf (TEXT("%.*ls"), uTextLenght, pszText);
//_puttchar();
//fwrite (pszText, sizeof(TCHAR), uTextLenght, stdout);
//_write (
}
So if one changes the value of STD_OUTPUT_HANDLE all output will be go to a file/pipe and so on. If instead of WriteFile the program use WriteConsole function such redirection will not works, but standard C/C++ library don't do this.
If you want redirect of stdout not from the child process but from the current process you can call SetStdHandle() directly (see http://msdn.microsoft.com/en-us/library/ms686244%28VS.85%29.aspx).
The "allocating of console" do a loader of operation system. It looks the word of binary EXE file (in the Subsystem part of IMAGE_OPTIONAL_HEADER see http://msdn.microsoft.com/en-us/library/ms680339%28VS.85%29.aspx) and if the EXE has 3 on this place (IMAGE_SUBSYSTEM_WINDOWS_CUI), than it use console of the parent process or create a new one. One can change a little this behavior in parameters of CreateProcess call (but only if you start child process in your code). This Subsystem flag of the EXE you define with respect of linker switch /subsystem (see http://msdn.microsoft.com/en-us/library/fcc1zstk%28VS.80%29.aspx).
If you want to redirect printf to a handle (FILE*), just do
fprintf(handle, "...");
For example replicating printf with fprintf
fprintf(stdout, "...");
Or error reporting
fprintf(stderr, "FATAL: %s fails", "smurf");
This is also how you write to files. fprintf(file, "Blah.");

Resources