|
|
1bab02 |
/*********************************************************/
|
|
|
1bab02 |
/* ptycon: a pty-console bridge */
|
|
|
f25e99 |
/* Copyright (C) 2016--2017 SysDeer Technologies, LLC */
|
|
|
1bab02 |
/* Released under GPLv2 and GPLv3; see COPYING.PTYCON. */
|
|
|
1bab02 |
/*********************************************************/
|
|
|
1bab02 |
|
|
|
1bab02 |
#include <psxtypes/psxtypes.h>
|
|
|
1bab02 |
#include <ntcon/ntcon.h>
|
|
|
1bab02 |
#include <ntapi/ntapi.h>
|
|
|
1bab02 |
#include <gdi/gdi.h>
|
|
|
1bab02 |
|
|
|
1bab02 |
#include <ptycon/ptycon.h>
|
|
|
1bab02 |
#include "ptycon_driver_impl.h"
|
|
|
1bab02 |
|
|
|
029664 |
typedef nt_unicode_conversion_params_utf16_to_utf8 uc_conv_params;
|
|
|
029664 |
|
|
|
77a707 |
extern const struct ptyc_vkcode ptyc_vkcode[0x100];
|
|
|
77a707 |
|
|
|
5ee033 |
static size_t ptyc_repeat(unsigned char * ch, size_t n, uint16_t count)
|
|
|
5ee033 |
{
|
|
|
5ee033 |
unsigned char * dst;
|
|
|
5ee033 |
int i;
|
|
|
5ee033 |
|
|
|
5ee033 |
if (!--count)
|
|
|
5ee033 |
return n;
|
|
|
5ee033 |
|
|
|
5ee033 |
if (n == 1) {
|
|
|
5ee033 |
for (i=count, dst=&ch[n]; i; i--) {
|
|
|
5ee033 |
dst[0] = ch[0];
|
|
|
5ee033 |
dst = &dst[n];
|
|
|
5ee033 |
}
|
|
|
5ee033 |
|
|
|
5ee033 |
} else if (n == 2) {
|
|
|
5ee033 |
for (i=count, dst=&ch[n]; i; i--) {
|
|
|
5ee033 |
dst[0] = ch[0];
|
|
|
5ee033 |
dst[1] = ch[1];
|
|
|
5ee033 |
dst = &dst[n];
|
|
|
5ee033 |
}
|
|
|
5ee033 |
|
|
|
5ee033 |
} else if (n == 3) {
|
|
|
5ee033 |
for (i=count, dst=&ch[n]; i; i--) {
|
|
|
5ee033 |
dst[0] = ch[0];
|
|
|
5ee033 |
dst[1] = ch[1];
|
|
|
5ee033 |
dst[2] = ch[2];
|
|
|
5ee033 |
dst = &dst[n];
|
|
|
5ee033 |
}
|
|
|
5ee033 |
|
|
|
5ee033 |
} else if (n == 4) {
|
|
|
5ee033 |
for (i=count, dst=&ch[n]; i; i--) {
|
|
|
5ee033 |
dst[0] = ch[0];
|
|
|
5ee033 |
dst[1] = ch[1];
|
|
|
5ee033 |
dst[2] = ch[2];
|
|
|
5ee033 |
dst[3] = ch[3];
|
|
|
5ee033 |
dst = &dst[n];
|
|
|
5ee033 |
}
|
|
|
5ee033 |
}
|
|
|
5ee033 |
|
|
|
5ee033 |
return n*count;
|
|
|
5ee033 |
}
|
|
|
5ee033 |
|
|
|
77a707 |
static size_t ptyc_translate_virtual_keycode(
|
|
|
77a707 |
nt_input_record * rec,
|
|
|
77a707 |
unsigned char * ch)
|
|
|
77a707 |
{
|
|
|
77a707 |
ntapi->tt_generic_memcpy(
|
|
|
77a707 |
ch,
|
|
|
77a707 |
ptyc_vkcode[rec->key_event.virtual_key_code].mbstr,
|
|
|
77a707 |
ptyc_vkcode[rec->key_event.virtual_key_code].mblen);
|
|
|
77a707 |
|
|
|
77a707 |
return ptyc_repeat(
|
|
|
77a707 |
ch,
|
|
|
77a707 |
ptyc_vkcode[rec->key_event.virtual_key_code].mblen,
|
|
|
77a707 |
rec->key_event.repeat_count);
|
|
|
77a707 |
}
|
|
|
77a707 |
|
|
|
029664 |
static size_t ptyc_translate_keyboard_event(
|
|
|
029664 |
nt_input_record * rec,
|
|
|
029664 |
unsigned char * ch,
|
|
|
029664 |
wchar16_t * wch)
|
|
|
029664 |
{
|
|
|
029664 |
wchar16_t src[2];
|
|
|
029664 |
wchar16_t recwch;
|
|
|
029664 |
uint32_t nbytes;
|
|
|
029664 |
uc_conv_params params = {0,0,0,0,0,0,0,0,0};
|
|
|
029664 |
|
|
|
029664 |
if (!rec->key_event.key_down)
|
|
|
029664 |
return 0;
|
|
|
029664 |
|
|
|
029664 |
if (!(recwch = rec->key_event.unicode_char))
|
|
|
77a707 |
return ptyc_translate_virtual_keycode(
|
|
|
77a707 |
rec,ch);
|
|
|
029664 |
|
|
|
083e87 |
if (recwch == 0x08)
|
|
|
083e87 |
recwch = 0x7f;
|
|
|
083e87 |
|
|
|
029664 |
if (*wch) {
|
|
|
029664 |
if ((recwch < 0xDC00) || (recwch >= 0xE000)) {
|
|
|
029664 |
*wch = 0;
|
|
|
029664 |
return 0;
|
|
|
029664 |
} else {
|
|
|
029664 |
src[0] = *wch;
|
|
|
029664 |
src[1] = recwch;
|
|
|
029664 |
*wch = 0;
|
|
|
029664 |
nbytes = 2*sizeof(wchar16_t);
|
|
|
029664 |
}
|
|
|
029664 |
} else if ((recwch >= 0xD800) && (recwch < 0xDC00)) {
|
|
|
029664 |
*wch = recwch;
|
|
|
029664 |
return 0;
|
|
|
029664 |
|
|
|
029664 |
} else {
|
|
|
029664 |
src[0] = recwch;
|
|
|
029664 |
nbytes = sizeof(wchar16_t);
|
|
|
029664 |
}
|
|
|
029664 |
|
|
|
029664 |
params.src = src;
|
|
|
029664 |
params.src_size_in_bytes = nbytes;
|
|
|
029664 |
params.dst = ch;
|
|
|
029664 |
params.dst_size_in_bytes = 4;
|
|
|
029664 |
|
|
|
029664 |
ntapi->uc_convert_unicode_stream_utf16_to_utf8(
|
|
|
029664 |
¶ms);
|
|
|
029664 |
|
|
|
5ee033 |
return ptyc_repeat(
|
|
|
5ee033 |
ch,
|
|
|
5ee033 |
params.bytes_written,
|
|
|
5ee033 |
rec->key_event.repeat_count);
|
|
|
029664 |
}
|
|
|
029664 |
|
|
|
029664 |
static size_t ptyc_translate_mouse_event(
|
|
|
029664 |
nt_input_record * rec,
|
|
|
029664 |
unsigned char * ch)
|
|
|
029664 |
{
|
|
|
029664 |
(void)rec;
|
|
|
029664 |
(void)ch;
|
|
|
029664 |
return 0;
|
|
|
029664 |
}
|
|
|
029664 |
|
|
|
029664 |
static size_t ptyc_translate_window_event(nt_input_record * rec)
|
|
|
029664 |
{
|
|
|
029664 |
(void)rec;
|
|
|
029664 |
return 0;
|
|
|
029664 |
}
|
|
|
029664 |
|
|
|
029664 |
static size_t ptyc_translate_menu_event(nt_input_record * rec)
|
|
|
029664 |
{
|
|
|
029664 |
(void)rec;
|
|
|
029664 |
return 0;
|
|
|
029664 |
}
|
|
|
029664 |
|
|
|
029664 |
static size_t ptyc_translate_focus_event(nt_input_record * rec)
|
|
|
029664 |
{
|
|
|
029664 |
(void)rec;
|
|
|
029664 |
return 0;
|
|
|
029664 |
}
|
|
|
029664 |
|
|
|
029664 |
static size_t ptyc_translate_event(
|
|
|
029664 |
nt_input_record * rec,
|
|
|
029664 |
unsigned char * ch,
|
|
|
029664 |
wchar16_t * wch)
|
|
|
029664 |
{
|
|
|
029664 |
switch (rec->event_type) {
|
|
|
029664 |
case NT_KEY_EVENT:
|
|
|
029664 |
return ptyc_translate_keyboard_event(
|
|
|
029664 |
rec,ch,wch);
|
|
|
029664 |
|
|
|
029664 |
case NT_MOUSE_EVENT:
|
|
|
029664 |
return ptyc_translate_mouse_event(
|
|
|
029664 |
rec,ch);
|
|
|
029664 |
|
|
|
029664 |
case NT_WINDOW_BUFFER_SIZE_EVENT:
|
|
|
029664 |
return ptyc_translate_window_event(rec);
|
|
|
029664 |
|
|
|
029664 |
case NT_MENU_EVENT:
|
|
|
029664 |
return ptyc_translate_menu_event(rec);
|
|
|
029664 |
|
|
|
029664 |
case NT_FOCUS_EVENT:
|
|
|
029664 |
return ptyc_translate_focus_event(rec);
|
|
|
029664 |
}
|
|
|
029664 |
|
|
|
029664 |
return 0;
|
|
|
029664 |
}
|
|
|
029664 |
|
|
|
5399d4 |
int __stdcall ptyc_console_reader(struct ptyc_driver_ctx_impl * ictx)
|
|
|
1bab02 |
{
|
|
|
029664 |
int32_t status;
|
|
|
029664 |
void * hwait;
|
|
|
029664 |
nt_iosb iosb;
|
|
|
029664 |
uint32_t nevents;
|
|
|
029664 |
size_t nbytes;
|
|
|
029664 |
wchar16_t wch;
|
|
|
029664 |
unsigned char * ch;
|
|
|
029664 |
unsigned i;
|
|
|
029664 |
|
|
|
029664 |
if ((status = ntapi->tt_create_private_event(
|
|
|
029664 |
&hwait,
|
|
|
029664 |
NT_NOTIFICATION_EVENT,
|
|
|
029664 |
NT_EVENT_NOT_SIGNALED)))
|
|
|
029664 |
return status;
|
|
|
029664 |
|
|
|
029664 |
do {
|
|
|
029664 |
if (!(ntcon->read_console_input_utf16(
|
|
|
029664 |
ictx->tctx.hin,
|
|
|
029664 |
ictx->tctx.input.events,
|
|
|
029664 |
PTYC_RAW_EVENTS,
|
|
|
029664 |
&nevents)))
|
|
|
029664 |
return NT_STATUS_ALREADY_DISCONNECTED;
|
|
|
029664 |
|
|
|
029664 |
for (ch=ictx->tctx.input.stream, i=0; i
|
|
|
029664 |
ch += ptyc_translate_event(
|
|
|
029664 |
&ictx->tctx.input.events[i],
|
|
|
029664 |
ch,&wch;;
|
|
|
029664 |
|
|
|
029664 |
nbytes = ch - ictx->tctx.input.stream;
|
|
|
029664 |
ch = ictx->tctx.input.stream;
|
|
|
029664 |
|
|
|
029664 |
for (; nbytes; ) {
|
|
|
029664 |
status = ntapi->pty_write(
|
|
|
029664 |
ictx->cctx.hptm,
|
|
|
1317da |
hwait,0,0,&iosb,
|
|
|
1317da |
ch,(uint32_t)nbytes,
|
|
|
029664 |
0,0);
|
|
|
029664 |
|
|
|
029664 |
if (status == NT_STATUS_PENDING)
|
|
|
029664 |
status = ntapi->zw_wait_for_single_object(
|
|
|
029664 |
hwait,NT_SYNC_ALERTABLE,0);
|
|
|
029664 |
|
|
|
029664 |
if (status || iosb.status) {
|
|
|
029664 |
ntapi->zw_close(hwait);
|
|
|
029664 |
return status ? status : iosb.status;
|
|
|
029664 |
}
|
|
|
029664 |
|
|
|
029664 |
ch += iosb.info;
|
|
|
029664 |
nbytes -= iosb.info;
|
|
|
029664 |
}
|
|
|
029664 |
} while (1);
|
|
|
029664 |
|
|
|
029664 |
return NT_STATUS_INTERNAL_ERROR;
|
|
|
1bab02 |
}
|