More WinAPI problems

2012-07-20 Thread DLimited

Hello everyone,

I encountered a few more problems while creating my system-wide 
makro program.


1)
I can't load my dll with LoadLibraryW, only LoadLibraryA. Why?

2)
The LoadLibraryA function fails with Error Code 127 - I still 
get a Handle and can register my function as a 
LowLevelKeyboardProc, so I'm not really sure what went wrong. 
Google tells me Code 127 means my .dll is dependant on other 
.dlls which can't be found, but I have no idea which/why/how.


3)
I intend to use the SendInput function to simulate Unicode 
character presses - to be precise, I want to inject this -- 
ಠ_ಠ -- whenever I press CTRL+SHIFT+ALT+Q  (for example). 
Sadly SendInput gives me Error Code 87 (Incorrect Parameter), 
but I don't know what I'm doing wrong.


I hope you guys can help me out!

This is the .dll code:

 - CODE BEGIN - 
import std.c.windows.windows;
import core.sys.windows.dll;
import core.runtime;
import std.stdio;

//const auto INPUT_KEYBOARD = 1;
//const auto KEYEVENTF_UNICODE = 4;

extern (C) void gc_init();
extern (C) void gc_term();
extern (C) void _minit();
extern (C) void _moduleCtor();
extern (C) void _moduleDtor();

extern (Windows) struct KBDLLHOOKSTRUCT {
  DWORD vkCode;
  DWORD scanCode;
  DWORD flags;
  DWORD time;
  ULONG_PTR dwExtraInfo;
};

extern (Windows) struct KEYBDINPUT {
  WORD  wVk;
  WORD  wScan;
  DWORD dwFlags;
  DWORD time;
  ULONG_PTR dwExtraInfo;
};


extern (Windows) struct INPUT {
DWORD type;

KEYBDINPUT ki;

};

extern (Windows) LRESULT CallNextHookEx(
HANDLE hhk,
  int nCode,
   WPARAM wParam,
LPARAM lParam
);

extern (Windows) SHORT GetKeyState(
int nVirtKey
);

extern (Windows) UINT SendInput(
UINT nInputs,
INPUT* pInputs,
int cbSize
);


__gshared HINSTANCE g_hInst;


 extern (Windows) BOOL DllMain(HINSTANCE hInstance, ULONG 
ulReason, LPVOID pvReserved) {

g_hInst = hInstance;
switch (ulReason) {
case DLL_PROCESS_ATTACH:
g_hInst = hInstance;
Runtime.initialize;
//dll_process_attach( hInstance, true );
break;

case DLL_PROCESS_DETACH:
//dll_process_detach( hInstance, true );
break;

case DLL_THREAD_ATTACH:
//dll_thread_attach( true, true );
break;
case DLL_THREAD_DETACH:
//dll_thread_detach( true, true );
break;

default:
return true;
}
return true;
}

extern (Windows) LRESULT LowLevelKeyboardProc(int code, WPARAM 
wParam, LPARAM lParam)

{
Runtime.initialize;
//MessageBoxA(null, HALLO, OK,0);
KBDLLHOOKSTRUCT* details = cast(KBDLLHOOKSTRUCT*) lParam;

if(code == 0  wParam == WM_KEYDOWN)
{
if(details.vkCode == 0x51) {

SHORT shiftkey = GetKeyState( VK_SHIFT );
SHORT ctrlkey = GetKeyState( VK_CONTROL );
SHORT altkey = GetKeyState ( VK_MENU );
		if( ( shiftkey == -127 || shiftkey == -128 )  ( ctrlkey == 
-127 || ctrlkey == -128 )  ( altkey == -127 || altkey == -128 ) 
)

{
//MessageBoxA(null, BOOM, OK,0);

INPUT[3] toSend = new INPUT[3];
toSend[0].type = 1;
toSend[0].ki.wVk = 0;
toSend[0].ki.wScan = 0x0CA0;
toSend[0].ki.dwFlags = 4;
toSend[0].ki.time = 0;
toSend[0].ki.dwExtraInfo = details.dwExtraInfo;

toSend[1].type = 1;
toSend[1].ki.wVk = 0;
toSend[1].ki.wScan = 0x005F;
toSend[1].ki.dwFlags = 4;
toSend[1].ki.time = 0;
toSend[1].ki.dwExtraInfo = details.dwExtraInfo;

toSend[2].type = 1;
toSend[2].ki.wVk = 0;
toSend[2].ki.wScan = 0x0CA0;
toSend[2].ki.dwFlags = 4;
toSend[2].ki.time = 0;
toSend[2].ki.dwExtraInfo = details.dwExtraInfo;
SendInput( cast(UINT)3, toSend.ptr, 
toSend[0].sizeof );
writeln(GetLastError());
//MessageBoxA(null, cast(char*)GetLastError(), 
OK,0);


return 1;
}
 

WinAPI LowLevel Keyboard Hooks

2012-07-19 Thread DLimited

Hello everyone,

I had this great idea of writing a Program that intercepts all
keyboard presses and modifies them in certain cases.
I want to use it as some kind of global makro program to run in
the background and for example allow me to easily post unicode
smileys.

This is where the probelms begin.
If I understood the WinAPI doc correctly, I need to install a
LowLevel Keyboard Hook using SetWindowsHookEx().

Unfortunately there are two versions of this function,
SetWindowsHookExW and SetWindowsHookExA. What's the difference?

The function to get called is passed as a parameter, but
apparently it needs to be located in a .dll if using global hooks.


So I need to first load my .dll file using LoadLibraryA( ) or
LoadLibraryW( ), locate my function using GetProcAddress( ) and
then set the hook using SetWindowsHookExW (or *-A)).


Unfortunately for me, even the LoadLibrary function fails,
returning Module could not be found. Now I'm 99% sure my .dll
is crap because this is the first time I ever wrote one, but it
DOES have a DllMain(), initializes the D Runtime and also has the
other function I want to install the hook for.

I'm hoping some bright minds here could help me out because
google didn't, and I'm out of my depth.
If you want me to, I'll post the source code, but I didn't want
this post to get too big, which still did, but anyway.


Re: WinAPI LowLevel Keyboard Hooks

2012-07-19 Thread DLimited
But what are the differences of loading the Unicode version vs. 
the ANSI version? I called the Unicode one because I figured that 
would be the sensible choice, since Unicode is the default for D 
(if I remember correctly). I have no clue what the actual effects 
of calling the wrong version would be.


Anyway, here's the of my .dll:

 -- Code begin -- 

import std.c.windows.windows;
import core.sys.windows.dll;
import core.runtime;


extern (C) void gc_init();
extern (C) void gc_term();
extern (C) void _minit();
extern (C) void _moduleCtor();
extern (C) void _moduleDtor();

extern (Windows) struct KBDLLHOOKSTRUCT {
  DWORD vkCode;
  DWORD scanCode;
  DWORD flags;
  DWORD time;
  ULONG_PTR dwExtraInfo;
};
extern (Windows) LRESULT CallNextHookEx(
int function() hhk,
  int nCode,
   WPARAM wParam,
LPARAM lParam
);


__gshared HINSTANCE g_hInst;


 extern (Windows) BOOL DllMain(HINSTANCE hInstance, ULONG 
ulReason, LPVOID pvReserved) {

return true;
switch (ulReason) {
case DLL_PROCESS_ATTACH:
g_hInst = hInstance;
Runtime.initialize;
//dll_process_attach( hInstance, true );
break;

case DLL_PROCESS_DETACH:
dll_process_detach( hInstance, true );
break;

case DLL_THREAD_ATTACH:
dll_thread_attach( true, true );
break;
case DLL_THREAD_DETACH:
dll_thread_detach( true, true );
break;

default:
return true;
}
return true;
}

extern (Windows) LRESULT LowLevelKeyboardProc(int code, WPARAM 
wParam, LPARAM lParam)

{
KBDLLHOOKSTRUCT* details = cast(KBDLLHOOKSTRUCT*) lParam;
MessageBoxA(null, cast(char *)WHOA, Error,
MB_OK | MB_ICONEXCLAMATION);
if(code == 0  wParam == WM_KEYDOWN)
{
if(details.vkCode == 0x41)
{

return 1;
}
}

return CallNextHookEx(null, code, wParam, lParam);
}

 -- Code End -- 

Lots of copypaste was used. I injected some senseless code to 
try and check if a specific function ever gets called, though I 
now realise the DllLoad itself is what fails. Haven't cleaned it 
back up yet, though.


The .def file contains the following: (including newlines)

 -- .DEF BEGIN -- 
LIBRARY keydll.dll
EXETYPE NT
SUBSYSTEM WINDOWS
CODE PRELOAD
DATA PRELOAD
 -- .DEF END   -- 


I compiled the dll using:
dmd -ofkeydll.dll -L/IMPLIB keydll.d keydll.def

No linker/compiler errors.


Re: WinAPI LowLevel Keyboard Hooks

2012-07-19 Thread DLimited


I guess you have to 'export' the function:
extern (Windows) export LRESULT LowLevelKeyboardProc(int code, 
WPARAM

wParam, LPARAM lParam)

and include
EXPORTS
  LowLevelKeyboardProc

in the .DEF file


Thanks, I changed that. Also, I changed LoadLibraryW( ) to
LoadLibraryA( ) in the main program and now it works (kinda). I
feel stupid now, although I still don't get why it wouldn't work
with LoadLibraryW.


Re: WinAPI LowLevel Keyboard Hooks

2012-07-19 Thread DLimited

On Thursday, 19 July 2012 at 16:38:19 UTC, DLimited wrote:


I guess you have to 'export' the function:
extern (Windows) export LRESULT LowLevelKeyboardProc(int code, 
WPARAM

wParam, LPARAM lParam)

and include
EXPORTS
 LowLevelKeyboardProc

in the .DEF file


Thanks, I changed that. Also, I changed LoadLibraryW( ) to
LoadLibraryA( ) in the main program and now it works (kinda). I
feel stupid now, although I still don't get why it wouldn't work
with LoadLibraryW.


Acutally, that was only the half-truth. The .dll seems to get 
loaded correctly ( GetLastError returns 0), but my 
keyboard-presses aren't captured at all.
My system seems to freeze up for ~5sec, after which everything 
resumes. Any keyboard input seems to get buffered and is 
processed by my terminal after my program closes.


Also I'm unsure about types because the often-used HHOOK is not 
defined with my imports, so I'm left guessing what it is. I used 
the type int function() instead (my best guess).


Here's the code:

 --- CODE BEGIN - 

import std.c.windows.windows;
import std.stdio;
import core.thread;

extern (C) void gc_init();
extern (C) void gc_term();
extern (C) void _minit();
extern (C) void _moduleCtor();
extern (C) void _moduleDtor();
extern (C) void _moduleUnitTests();
extern (Windows) int function() SetWindowsHookExA( int idHook,
HOOKPROC lpfn,
HINSTANCE hMod,
DWORD dwThreadId );
extern (Windows) struct KBDLLHOOKSTRUCT {
  DWORD vkCode;
  DWORD scanCode;
  DWORD flags;
  DWORD time;
  ULONG_PTR dwExtraInfo;
};
extern (Windows) LRESULT CallNextHookEx(
int function() hhk,
  int nCode,
   WPARAM wParam,
LPARAM lParam
);

extern (Windows) bool UnhookWindowsHookEx(
   int function() hhk
);

extern (Windows) HMODULE LoadLibraryA(
   LPCTSTR lpFileName
);



extern (Windows)
int WinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR lpCmdLine,
int nCmdShow)
{
int result;

gc_init();  // initialize garbage collector
_minit();   // initialize module constructor table

try
{
_moduleCtor();  // call module constructors
//_moduleUnitTests();   // run unit tests (optional)

	result = myWinMain(hInstance, hPrevInstance, lpCmdLine, 
nCmdShow);


_moduleDtor();  // call module destructors
}

catch (Exception o) // catch any uncaught exceptions
{
MessageBoxA(null, cast(char *)o.toString(), Error,
MB_OK | MB_ICONEXCLAMATION);
result = 0; // failed
}

gc_term();  // run finalizers; terminate garbage collector
return result;
}

int myWinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR lpCmdLine,
int nCmdShow)
{

HOOKPROC hkprcSysMsg;
HINSTANCE hinstDLL;
extern (Windows) int function() hhookSysMsg;

hinstDLL = 
LoadLibraryA(cast(LPCTSTR)correct_absolute_path\\keydll.dll);

writeln(GetLastError()); //returns 0
hkprcSysMsg = cast(HOOKPROC)GetProcAddress(hinstDLL, 
LowLevelKeyboardProc);

writeln(GetLastError()); //return 0
hhookSysMsg = SetWindowsHookExA(
13,
hkprcSysMsg,
hinstDLL,
0);

writeln(GetLastError()); // returns 0 aswell
Thread.sleep( dur!(seconds)(10) );
UnhookWindowsHookEx( hhookSysMsg );

return 0;
}


Re: WinAPI LowLevel Keyboard Hooks

2012-07-19 Thread DLimited

On Thursday, 19 July 2012 at 17:35:29 UTC, dnewbie wrote:

You don't see the WHOA message?
Try this
alias HANDLE HHOOK;


No, I don't get any message after key-presses. I changed int 
function() to HANDLE, sadly it still doesn't work.


Re: WinAPI LowLevel Keyboard Hooks

2012-07-19 Thread DLimited

On Thursday, 19 July 2012 at 18:40:15 UTC, dnewbie wrote:

On Thursday, 19 July 2012 at 17:48:06 UTC, DLimited wrote:

On Thursday, 19 July 2012 at 17:35:29 UTC, dnewbie wrote:

You don't see the WHOA message?
Try this
alias HANDLE HHOOK;


No, I don't get any message after key-presses. I changed int 
function() to HANDLE, sadly it still doesn't work.



For some reason, it doesn't work with 'Thread.sleep'
This works:
http://dpaste.dzfl.pl/1e6e5960


It doesn't work for me. I can 1 Message Box from the Code in 
MyWinMain, but none for the Keystrokes. I registered a hook for 
Keyboard input, and that code is supposed to produce a message 
box aswell. The function for that is called LowLevelKeyboardProc 
and located in above-mentioned .dll file.


The registering of the hook seems to pass, but the function never 
actually gets called.


Re: WinAPI LowLevel Keyboard Hooks

2012-07-19 Thread DLimited

On Thursday, 19 July 2012 at 19:43:45 UTC, dnewbie wrote:

On Thursday, 19 July 2012 at 18:56:15 UTC, DLimited wrote:

On Thursday, 19 July 2012 at 18:40:15 UTC, dnewbie wrote:

On Thursday, 19 July 2012 at 17:48:06 UTC, DLimited wrote:

On Thursday, 19 July 2012 at 17:35:29 UTC, dnewbie wrote:

You don't see the WHOA message?
Try this
alias HANDLE HHOOK;


No, I don't get any message after key-presses. I changed int 
function() to HANDLE, sadly it still doesn't work.



For some reason, it doesn't work with 'Thread.sleep'
This works:
http://dpaste.dzfl.pl/1e6e5960


It doesn't work for me. I can 1 Message Box from the Code in 
MyWinMain, but none for the Keystrokes. I registered a hook 
for Keyboard input, and that code is supposed to produce a 
message box aswell. The function for that is called 
LowLevelKeyboardProc and located in above-mentioned .dll file.


The registering of the hook seems to pass, but the function 
never actually gets called.


Did you add
EXPORTS
LowLevelKeyboardProc

to the .DEF file?
It works here.


Yes, I did. Are the newlines important?

And you really get a MessageBox per keystroke? I start as admin, 
disabled my AV but still, no success.


Re: WinAPI LowLevel Keyboard Hooks

2012-07-19 Thread DLimited

On Thursday, 19 July 2012 at 20:06:55 UTC, dnewbie wrote:

On Thursday, 19 July 2012 at 19:51:31 UTC, DLimited wrote:

Yes, I did. Are the newlines important?

And you really get a MessageBox per keystroke? I start as 
admin, disabled my AV but still, no success.


Yes, I get 2 WHOA messages. One from the WM-KEYDOWN and the 
other from WM-KEYUP.

Sorry I don't know what is wrong.


THANK YOU for your help! It works now!

I didn't call Runtime.initialize; in my exported function because 
I thought the runtime would already be initialized in the DllMain 
- seems like that is not the case. Wouldn't have thought of it if 
I hadn't had your sample code, though!


Thanks a ton!