Native Application之键盘处理

作者:Robinh00d
高手可以飘过了,这段代码是用于NATIVE APPLICATION支持键盘输入用的,测试PS/2键盘好用,USB键盘未测
就是循环从KeyboardClassX里读键盘数据而已~

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
#define MAX_KEYBOARD_COUNT 10
HANDLE hKbdTable[MAX_KEYBOARD_COUNT];
HANDLE hReadKbdEvt[MAX_KEYBOARD_COUNT];
USHORT KbdInputBuffer[16] = {0};
 
 
UCHAR ScancodeTable[] =
{
0,
0, //ESC
'1','2','3','4','5','6','7','8','9','0',
0,0,0,0,
'Q','W','E','R','T','Y','U','I','O','P',
0,0,
0, //ENTER
0,
'A','S','D','F','G','H','J','K','L',
0,0,0,0,0,
'Z','X','C','V','B','N','M'
};
 
BOOLEAN KeyboardHandler(PULONG pulResult)
{
	HANDLE hKbdDevice = NULL;
	ULONG i = 0;
	ULONG ulKbdNum = 0;
	PWCHAR szwKbdDeviceName = NULL;
	OBJECT_ATTRIBUTES ObjectAttributes;
	NTSTATUS ntStatus = STATUS_UNSUCCESSFUL;
	UNICODE_STRING usDeviceName;
	PIO_STATUS_BLOCK pIoStatusBlocks = NULL;
	LARGE_INTEGER TimeOut;
	LARGE_INTEGER ByteOffset;
	ULONG ulCharCount = 0;
	BOOLEAN bIsEsc = FALSE; //是否输入了ESC
	BOOLEAN bIsEnter = FALSE; //是否输入了回车
	BOOLEAN bIsScanAllDrive = FALSE; //扫描全盘标志位
	WCHAR szwPrintMsg[16] = {0};
	KEYBOARD_INPUT_DATA KeyboardInputData = {0};
 
	ASSERT(pulResult != NULL);
 
	__asm int 3
	szwKbdDeviceName = (PWCHAR)RtlAllocateHeap(Heap, 0, 128);
 
	if (NULL == szwKbdDeviceName)
	{
		return FALSE;
	}
 
	pIoStatusBlocks = (PIO_STATUS_BLOCK)RtlAllocateHeap(Heap, 0, sizeof(IO_STATUS_BLOCK)*MAX_KEYBOARD_COUNT);
 
	if (NULL == pIoStatusBlocks)
	{
		return FALSE;
	}
 
	//
	// 尝试打开系统中所有的键盘设备
	//
	for (; i < MAX_KEYBOARD_COUNT; i++)
	{
		RtlZeroMemory(szwKbdDeviceName, 128);
 
		swprintf(szwKbdDeviceName, L"\\Device\\KeyboardClass%d", i);
 
		RtlInitUnicodeString(&usDeviceName,szwKbdDeviceName);
 
		InitializeObjectAttributes(&ObjectAttributes,&usDeviceName,OBJ_CASE_INSENSITIVE ,NULL,NULL);
 
		ntStatus = NtCreateFile(&hKbdDevice, \
				0x80100080,
				&ObjectAttributes, &pIoStatusBlocks[i], NULL, FILE_ATTRIBUTE_NORMAL, 0, 1, 1, NULL ,0);
 
		if (NT_SUCCESS(ntStatus))
		{
			hKbdTable[ulKbdNum] = hKbdDevice;
			InitializeObjectAttributes(&ObjectAttributes, NULL, 0, NULL, NULL);
			ntStatus = NtCreateEvent(&hReadKbdEvt[ulKbdNum], 0x1F01FF, NULL, SynchronizationEvent, FALSE);
 
			ulKbdNum++;
		}
 
	}
 
	TimeOut.QuadPart = -10 * 1000 * 1000;
	TimeOut.QuadPart *= 10;
 
	ByteOffset.QuadPart = 0;
 
	while(TRUE)
	{
		for (i = 0; i < ulKbdNum; i++)
		{
			ntStatus = NtReadFile(hKbdTable[i], hReadKbdEvt[i], NULL, NULL, &pIoStatusBlocks[i], &KeyboardInputData, sizeof(KEYBOARD_INPUT_DATA), &ByteOffset, NULL);
 
			if (ntStatus == STATUS_PENDING)
			{
				ntStatus = NtWaitForSingleObject(hReadKbdEvt[i], FALSE, &TimeOut);
 
				if (ntStatus == STATUS_TIMEOUT)
				{
					NtCancelIoFile(hKbdTable[i], &pIoStatusBlocks[i]);
				}
				else
				{
					//保存数据
					if (KeyboardInputData.MakeCode == 0x1C) //如果是回车
					{
					    bIsEnter = TRUE;
					    break;
					}
					else if (KeyboardInputData.MakeCode == 0x01) //如果是ESC
					{
					    bIsEsc = TRUE;
					    break;
					}
					else if (KeyboardInputData.MakeCode == 0x3B) //如果是F1键 则扫描全盘
					{
					    bIsScanAllDrive = TRUE;
					    break;
					}
 
					if (KeyboardInputData.Flags == 0)
					{
					    if (KeyboardInputData.MakeCode<sizeof(ScancodeTable))
                        {
                            //则不做任何处理
                            swprintf(szwPrintMsg, L"%c", ScancodeTable[KeyboardInputData.MakeCode]);
					        DisplayString(szwPrintMsg);
 
					        if (ulCharCount &lt;16)
					            KbdInputBuffer[ulCharCount++] = ScancodeTable[KeyboardInputData.MakeCode];
                        }
					}
				}
			}
 
		}
 
		//如果输入了回车或者ESC键则停止记录键盘
 
	    if (bIsEnter)
	    {
	        *pulResult = 1;
	        break;
	    }
	    else if (bIsEsc)
	    {
	        *pulResult = 2;
	        break;
	    }
	    else if (bIsScanAllDrive)
	    {
	        *pulResult = 3;
	        break;
	    }
	}
 
	return TRUE;
}

效果:

GetKbdDemo

随机日志


    10 Responses to “Native Application之键盘处理”

    1. gz1x 说:

      挺好玩的。

      [回复]

    2. gz1x 说:

      好像代码贴的有问题。

      [回复]

      ayarei 回复:

      其实贴完整代码没什么意思呀~还是有点悬念自己改改的好~

      [回复]

    3. robinh00d 说:

      我少贴了几个全局变量~ 一会加上 还有 代码高亮功能还没弄好,等晚上ayarei下课后再弄~

      [回复]

    4. Rinrin 说:

      TinyKRNL里有个NCLI,不过只能处理一个键盘

      [回复]

    5. Azy 说:

      不错。。。

      [回复]

    6. mengxp 说:

      那行字没空格 -.-

      [回复]

    7. robinh00d 说:

      没支持空格~

      [回复]

    8. 0x4 说:

      怎么tab跟空格混用的,真难看

      全部替换成空格多好。

      [回复]

    9. 49513524 说:

      郁闷,对于大菜鸟来说代码贴不全很郁闷的.

      [回复]

    Post a Comment