difficult - Keyboard hook

Hi,
I need to do the following:
A barcode scanner is connected to the PS/2 input using a split cable (so, both the keyboard and the barcode scanner are connected to the same PS/2 port). The barcode scanner uses "keyboard simulation" to send it's code to the currently active application. If you open a texteditor and you scan a barcode, the number is send to the page.

You can add a "prefix" to the barcodescanner of maximum 10 keycodes or characters (like A, #, NULL,
SOHSTXETXEOTENQACKBEL
etc...)
I want to use the barodescanner on the background, so I was planning to use a system wide keyboard hook which detects if there was a NULL-NULL send to the PS/2 input, and in this case takes the 13 following characters (I'm using EAN13 as barcode) and makes that they are send to a file, without that they are send to the active apllication (like MS Word, Outlook, ...).
Some extra information: The PC's on which it must work doesn't have either .NET1 or .NET2 .

I tried to make some demo code, but apparently this code won't work (because the NULL's aren't captured):

LRESULT __declspec(dllexport)__stdcall CALLBACK KeyboardProc(int nCode,WPARAM wParam,
LPARAM lParam)
{
char ch;
if (((DWORD)lParam &0x40000000) &&(HC_ACTION==nCode))
{
if ((wParam==VK_SPACE)||(wParam==VK_RETURN)||(wParam>=0x2f ) &&(wParam<=0x100))
{
f1=fopen("c:\\report.txt","a+");
if (wParam==VK_RETURN)
{
ch='\n';
fwrite(&ch,1,1,f1);
}
else
{
BYTE ks[256];
GetKeyboardState(ks);

WORD w;
UINT scan=0;
ToAscii(wParam,scan,ks,&w,0);
ch =char(w);
fwrite(&ch,1,1,f1);
}
fclose(f1);
}
}

LRESULT RetVal = CallNextHookEx( hkb, nCode, wParam, lParam );
return RetVal;
}How should I adapt the code? Can someone give me some example code?
Thanks

[3829 byte] By [plinius] at [2007-12-28]
# 1
Those prefix codes don't make any sense. NULL is not a valid key code. SOH, STX etc are control codes (0x01 through 0x07). Keycode 0x01 is VK_LBUTTON. Instead, the scanner may generate a Ctrl+A, Ctrl+B, etc. Possibly, NULL is Ctrl+@. You'd better take a look first without using the keyboard hook.

You also might want to consider a hook set with WH_KEYBOARD_LL instead of WH_KEYBOARD. The latter requires Windows to inject your DLL into the process space of every running process.

nobugz at 2007-9-4 > top of Msdn Tech,Visual Studio Express Editions,Visual C++ 2005 Express Edition...
# 2
Thanks a lot. I followed your advice.
I made some code using a
SetWindowsHookEx (WH_KEYBOARD_LL, LowLevelKeyboardProc ,...);
I filtered like that:
(wParam != WM_KEYDOWN)&& (wParam != WM_KEYUP)
which works fine.
I do have one more question though:
What I want to do now is, when it's a barcode which is scanned, it's not passed to the active application.
Therefore I putted this at the end of the callback function:

LRESULT RetVal=NULL;
if (!wasbarcode)
RetVal = CallNextHookEx(hKeyHook, nCode,wParam,lParam);
return RetVal;

But this doesn't seems to work?! I'm positively sure that the filter does what it should do.
(the only reason I could think of is the following:
I'm not working with a dll to hook but with a single exe (like this):

__declspec(dllexport) LRESULT CALLBACK LowLevelKeyboardProc(int nCode, WPARAM wParam, LPARAM lParam ) {
bool wasbarcode=false;

What am I doing wrong ?
Should I work with a dll or is it something else I did wrong?

Thanks a lot !

plinius at 2007-9-4 > top of Msdn Tech,Visual Studio Express Editions,Visual C++ 2005 Express Edition...
# 3
The docs are confusing due to the nCode argument. However, if you *do* use the keystroke, you need to return a non-zero value to indicate that you used the keystroke and shouldn't be passed on the application. The code you posted is returning a zero. Try this:

LRESULT RetVal = (LRESULT)1;
if (!wasbarcode)
// Etc.

nobugz at 2007-9-4 > top of Msdn Tech,Visual Studio Express Editions,Visual C++ 2005 Express Edition...
# 4
I just tried that, and it doens't works .
It gave a very strange result:
every barcode was send to the application as before, exept all the 7's in the barcode were replaced by ?.
So, the code
8711875929908
Gave this in the "notepad-window":
8?118?5929908

I searched further but didn't found anything else...
Thanks.

plinius at 2007-9-4 > top of Msdn Tech,Visual Studio Express Editions,Visual C++ 2005 Express Edition...
# 5
OK. Found it. Now it works, but there's still one bug left:
whenever a barcode is scanned, the numpad doesn't works anymore...
Which is very annoying, because you have to unhook the application...

Here is the code (it's a bit ugly, should clean it up once...)

static bool wasbarcode=false;
static bool eerstevdtwee=true;
static int teller=0;
static int tempcijfer;

__declspec(dllexport) LRESULT CALLBACK LowLevelKeyboardProc(int nCode, WPARAM wParam, LPARAM lParam ) {

bool laatstealtweg=false;
if ((nCode == HC_ACTION) ) {
if ((unsigned char)wParam == 0x05) {//hier dus: barcode gedeelte
wasbarcode=true;
teller++;
if(teller==26){wasbarcode=false;/*teller=0;*/}
printf("\nteller:%i\n",teller);
BYTE KeyState[256];

KBDLLHOOKSTRUCT hooked = *((KBDLLHOOKSTRUCT*)lParam);

GetKeyboardState(KeyState);

printf("\n--flags:%x--scancode:%x--vkcode:%x--tempcijf:%i",hooked.flags,hooked.scanCode,hooked.vkCode,(int)hooked.vkCode-96);

if(eerstevdtwee)
{tempcijfer=(int)hooked.vkCode-96;}
else{//dus tweede!
tempcijfer=(10*tempcijfer +((int)hooked.vkCode-96))-48;
printf("%i",tempcijfer);
}
eerstevdtwee=!eerstevdtwee;
}//eind barcodegedeelte
else{//hierin moet laatste ALT weggewerkt worden ! anders:?
if(teller==26){teller=0;laatstealtweg=true;}
}
}
return((wasbarcode || laatstealtweg) ? (LRESULT)1 : CallNextHookEx(hKeyHook, nCode,wParam,lParam));
}

plinius at 2007-9-4 > top of Msdn Tech,Visual Studio Express Editions,Visual C++ 2005 Express Edition...
# 6
I can read Dutch but still have a hard time figuring out your code. The cast on wParam is pretty bizarre. I'm guessing it triggers the barcode reading on the WM_SYSKEYUP message. That is not sufficiently unique, WM_SYSKEYUP is generated for any keystroke with the Alt key down, including the Alt key itself.

You must pass non-character keys like VK_MENU (Alt), VK_CONTROL and VK_SHIFT unmodified. Not doing this would fatally confuse the application programs.

nobugz at 2007-9-4 > top of Msdn Tech,Visual Studio Express Editions,Visual C++ 2005 Express Edition...
# 7
Isn't

if ((nCode == HC_ACTION) ) {
if ((unsigned char)wParam == 0x05) {

only selecting the Alt? The Control and shift use another wParam !?

plinius at 2007-9-4 > top of Msdn Tech,Visual Studio Express Editions,Visual C++ 2005 Express Edition...
# 8
Check the docs, wParam doesn't contain the keycode, it contains WM_KEYDOWN/UP or WM_SYSKEYDOWN/UP. The keycode is lParam->vkCode. The key code for the ALT key is not 0x05, it is VK_MENU (0x12).
nobugz at 2007-9-4 > top of Msdn Tech,Visual Studio Express Editions,Visual C++ 2005 Express Edition...
# 9
Thanks; the problem is solved, now !
plinius at 2007-9-4 > top of Msdn Tech,Visual Studio Express Editions,Visual C++ 2005 Express Edition...