You would use NtDisplayString() to write strings to the console:
void OutputString(PWCHAR pwszText)
{
UNICODE_STRING usText;
usText.Buffer = pwszText;
usText.Length = wcslen(pwszText) * sizeof(WCHAR);
usText.MaximumLength = usText.Length + sizeof(WCHAR);
NtDisplayString(&usText);
}
To receive keyboard input you must open and read the keyboard device
directly:
HANDLE g_hKeyboardAsync = NULL;
NTSTATUS CreateKeyboard()
{
UNICODE_STRING ustrFileName;
HANDLE hKeyboard = NULL;
OBJECT_ATTRIBUTES oa;
IO_STATUS_BLOCK iosb;
NTSTATUS status;
PWCHAR pszFileName = L"\Device\KeyboardClass0";
RtlInitUnicodeString( &ustrFileName, pszFileName );
InitializeObjectAttributes (
&oa,
&ustrFileName,
OBJ_CASE_INSENSITIVE,
NULL,
NULL
);
memset( &iosb, 0, sizeof( iosb ) );
status = ZwCreateFile(
&g_hKeyboardAsync,
GENERIC_READ | SYNCHRONIZE | FILE_READ_ATTRIBUTES,
&oa,
&iosb,
0,
FILE_ATTRIBUTE_NORMAL,
0,
FILE_OPEN,
FILE_DIRECTORY_FILE,
NULL,
0
);
return status;
}
Once you have a handle to the keyboard device, NtWaitForSingleObject() on
it and if it returns STATUS_SUCCESS (as opposed to STATUS_PENDING) then
ZwReadFile() the handle to retrieve the make/break code and the scan code
value. You must translate the scan codes to ASCII codes yourself.
For the read, declare an array of type:
CHAR g_KeyBuf[0xf0];
The make/break code will be at g_KeyBuf[4], and the scan code will be at
g_KeyBuf[2]:
PWORD pwScanCode;
PWORD pwMakeBreak;
pwMakeBreak = ( PWORD ) &g_KeyBuf[4];
pwScanCode = ( PWORD ) &g_KeyBuf[2];
Hope this helps.
Rick Howard
Principal Engineer
Ontrack Data International, Inc.
Boulder,CO
You are currently subscribed to ntdev as: $subst(‘Recip.EmailAddr’)
To unsubscribe send a blank email to leave-ntdev-$subst(‘Recip.MemberIDChar’)@lists.osr.com