Strange problem with stdio

Strange problem with stdio

Post by madok » Sun, 27 Jul 2003 00:15:34


I'm trying to write a simple key logger program for Windows, so I
wrote a WH_KEYBOARD hook. In the KeyboardProc() callback, I used
fwrite() & printf() to store & output the captured keys.

However, my program will only reliably capture keystrokes if it's the
front-most application. If I had mistakenly installed the hook only
on the local thread, then I should get nothing in other apps. Also,
when I replaced all the stdio calls with Beep(), the code seems to
work. I've also tried to follow each output with fflush(), to no

Therefore, I believe that the problem has to do with stdio not working
correctly. So my question is why, and how can I fix it?

Thanks in advance.

Julian Hsiao

Strange problem with stdio

Post by Mike Caeta » Sun, 27 Jul 2003 11:10:42

That's peculiar.

There's code for a key logger using a keyboard hook at
lcc-win32. The hook callback calls printf. You might want to take a look at
that code and see if you can adapt it to fit your needs.



Strange problem with stdio

Post by madok » Sun, 27 Jul 2003 19:52:40


With a bit more experimentation, I found out that the problem isn't
with stdio. Rather, somehow any operations that require keeping
states will get lost: I tried incrementing a counter for every key
press instead of Beep(), and the counter will only increase if the
logging program is front-most. Any idea why this is the case?

The code here hooks to WH_KEYBOARD_LL instead of WH_KEYBOARD; when
changed hook on the latter the code doesn't work at all. However, it
works find with WH_KEYBOARD_LL. Guess I'll just have to do a bit more
work to parse the output.

Thanks for the pointer.

Julian Hsiao

Strange problem with stdio

Post by Mike Caeta » Sun, 27 Jul 2003 21:54:25

It's hard to say exactly, but it sounds like there's some interference with
the system input thread. I would think that keeping the logger front-most
would interfere with keyboard activity in another application - viz the
current focus. Perhaps changing to a low level keyboard hook will resolve
the issue? There's also thread synchronization to consider. Every process
has at least one thread, so hooking across processes indicates taking that
into consideration. You might consider placing the counter in shared memory
and protected it with a mutex or using it with InterlockedIncrement (and

Sure. One very noteable aspect of that code is that it demonstrates how to
establish a system wide hook in an exe file. That's not standard.


Strange problem with stdio

Post by Mike Caeta » Wed, 30 Jul 2003 09:44:56

Well, I think it makes sense considering that the module containing the
hooking code ends up loaded into every process currently running on the
desktop. MSDN documents that aspect of global hooks:

"A global hook monitors messages for all threads in the same desktop as the
calling thread. ... A global hook procedure can be called in the context of
any application in the same desktop as the calling thread, so the procedure
must be in a separate dynamic-link library (DLL) module. ... If the
application installs a hook procedure for a thread of a different
application, the procedure must be in a DLL."

But rather than point out the implications of this, the documenation merely
warns against using global hooks. (As if a warning was enough!) The doc
makes references to the section on DLLs, where the topic of using shared
memory is touched on
_a_dynamic_link_library.asp), but stops short of making the connection as to
exactly why this is important.

Imo, the SDK docs are generally insufficient so it pays to dig a little
deeper. And it's easier to use Google to search MSDN than the MSDN search -
just append "" on to the query. eg:

It turns out that MSDN does cover the issue in an article titled "Win32
Hooks" by Kyle Marsh: "Filter functions for systemwide hooks must be
prepared to share any data they need across the different processes they are
running from. A DLL is mapped into the address space of each of its client
processes. Global variables within the DLL will be instance specific unless
they are placed in a shared data section. "

A good explanation of hooks can be found here: , the code examples use a VC++
specific pragma related to shared memory.