|
|
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 |
#include "ptycon_status_impl.h"
|
|
|
1bab02 |
|
|
|
5399d4 |
int __stdcall ptyc_console_ctrl(uint32_t);
|
|
|
1bab02 |
|
|
|
5399d4 |
int __stdcall ptyc_console_reader(void *);
|
|
|
5399d4 |
int __stdcall ptyc_console_writer(void *);;
|
|
|
5399d4 |
int __stdcall ptyc_console_poller(void *);
|
|
|
1bab02 |
|
|
|
5399d4 |
int __stdcall ptyc_dbg_cat(struct ptyc_driver_ctx *);
|
|
|
5399d4 |
int __stdcall ptyc_dbg_event(void *);
|
|
|
5399d4 |
int __stdcall ptyc_dbg_oven(void *);
|
|
|
5399d4 |
int __stdcall ptyc_dbg_raw(void *);
|
|
|
1bab02 |
|
|
|
9cf365 |
|
|
|
1bab02 |
struct ptyc_loop_thread_ctx {
|
|
|
1bab02 |
nt_thread_start_routine * entry;
|
|
|
1bab02 |
struct ptyc_driver_ctx_impl * ictx;
|
|
|
1bab02 |
};
|
|
|
1bab02 |
|
|
|
dfc432 |
static int __stdcall ptyc_loop_thread_entry(void * ctx)
|
|
|
1bab02 |
{
|
|
|
1bab02 |
struct ptyc_loop_thread_ctx * xctx;
|
|
|
1bab02 |
|
|
|
1bab02 |
xctx = (struct ptyc_loop_thread_ctx *)ctx;
|
|
|
1bab02 |
|
|
|
1bab02 |
return ntapi->zw_terminate_thread(
|
|
|
1bab02 |
NT_CURRENT_THREAD_HANDLE,
|
|
|
1bab02 |
xctx->entry(xctx->ictx));
|
|
|
1bab02 |
}
|
|
|
1bab02 |
|
|
|
1bab02 |
static int ptyc_create_loop_thread(
|
|
|
1bab02 |
nt_thread_params * params,
|
|
|
1bab02 |
struct ptyc_driver_ctx_impl * ictx,
|
|
|
1bab02 |
nt_thread_start_routine * entry)
|
|
|
1bab02 |
{
|
|
|
1bab02 |
struct ptyc_loop_thread_ctx xctx;
|
|
|
1bab02 |
|
|
|
1bab02 |
xctx.entry = entry;
|
|
|
1bab02 |
xctx.ictx = ictx;
|
|
|
1bab02 |
|
|
|
1bab02 |
/* rapunzel rapunzel */
|
|
|
1bab02 |
params->hprocess = NT_CURRENT_PROCESS_HANDLE;
|
|
|
1bab02 |
params->start = ptyc_loop_thread_entry;
|
|
|
1bab02 |
params->ext_ctx = &xct;;
|
|
|
1bab02 |
params->ext_ctx_size = sizeof(xctx);
|
|
|
1bab02 |
params->stack_size_commit = 64 * 1024;
|
|
|
1bab02 |
params->stack_size_reserve = 64 * 1024;
|
|
|
1bab02 |
params->creation_flags = NT_CREATE_LOCAL_THREAD;
|
|
|
1bab02 |
|
|
|
1bab02 |
return ntapi->tt_create_thread(
|
|
|
1bab02 |
params);
|
|
|
1bab02 |
}
|
|
|
1bab02 |
|
|
|
1bab02 |
static int ptyc_free_console_impl(
|
|
|
1bab02 |
struct ptyc_driver_ctx_impl * ictx,
|
|
|
1bab02 |
int32_t status)
|
|
|
1bab02 |
{
|
|
|
1bab02 |
struct ptyc_term_ctx * tctx;
|
|
|
1bab02 |
struct ptyc_loop_ctx * lctx;
|
|
|
1bab02 |
|
|
|
1bab02 |
tctx = &ictx->tctx;
|
|
|
1bab02 |
lctx = &ictx->lctx;
|
|
|
1bab02 |
|
|
|
1bab02 |
if (tctx->hin)
|
|
|
1bab02 |
ntcon->free_console();
|
|
|
1bab02 |
|
|
|
1bab02 |
if (lctx->treader.hthread)
|
|
|
1bab02 |
ntapi->zw_close(lctx->treader.hthread);
|
|
|
1bab02 |
|
|
|
1bab02 |
if (lctx->twriter.hthread)
|
|
|
1bab02 |
ntapi->zw_close(lctx->twriter.hthread);
|
|
|
1bab02 |
|
|
|
1bab02 |
if (lctx->tpoller.hthread)
|
|
|
1bab02 |
ntapi->zw_close(lctx->tpoller.hthread);
|
|
|
1bab02 |
|
|
|
1bab02 |
if (lctx->tdbgevent.hthread)
|
|
|
1bab02 |
ntapi->zw_close(lctx->tdbgevent.hthread);
|
|
|
1bab02 |
|
|
|
1bab02 |
if (lctx->tdbgoven.hthread)
|
|
|
1bab02 |
ntapi->zw_close(lctx->tdbgoven.hthread);
|
|
|
1bab02 |
|
|
|
1bab02 |
if (lctx->tdbgraw.hthread)
|
|
|
1bab02 |
ntapi->zw_close(lctx->tdbgraw.hthread);
|
|
|
1bab02 |
|
|
|
1bab02 |
return status;
|
|
|
1bab02 |
}
|
|
|
1bab02 |
|
|
|
1bab02 |
static int ptyc_init_console(struct ptyc_term_ctx * tctx)
|
|
|
1bab02 |
{
|
|
|
1bab02 |
/* console input buffer) */
|
|
|
1bab02 |
if (!(tctx->hin = ntcon->get_std_handle(NT_STD_INPUT_HANDLE)))
|
|
|
1bab02 |
return NT_STATUS_UNSUCCESSFUL;
|
|
|
1bab02 |
|
|
|
1bab02 |
/* console screen buffer */
|
|
|
1bab02 |
if (!(tctx->hout = ntcon->create_console_screen_buffer(
|
|
|
1bab02 |
NT_GENERIC_READ | NT_GENERIC_WRITE,
|
|
|
1bab02 |
0,0,NT_CONSOLE_TEXTMODE_BUFFER,0)))
|
|
|
1bab02 |
return NT_STATUS_UNSUCCESSFUL;
|
|
|
1bab02 |
|
|
|
f7f963 |
if (!(ntcon->set_console_screen_buffer_size(
|
|
|
f7f963 |
tctx->hout,
|
|
|
f7f963 |
tctx->screen_size)))
|
|
|
f7f963 |
return NT_STATUS_UNSUCCESSFUL;
|
|
|
f7f963 |
|
|
|
1bab02 |
if (!(ntcon->set_console_active_screen_buffer(tctx->hout)))
|
|
|
1bab02 |
return NT_STATUS_UNSUCCESSFUL;
|
|
|
1bab02 |
|
|
|
1bab02 |
/* console text attributes: default colors */
|
|
|
1bab02 |
if (!(ntcon->set_console_text_attribute(
|
|
|
1bab02 |
tctx->hout,
|
|
|
1bab02 |
NT_BACKGROUND_BLACK | NT_FOREGROUND_WHITE)))
|
|
|
1bab02 |
return NT_STATUS_UNSUCCESSFUL;
|
|
|
1bab02 |
|
|
|
1bab02 |
/* console code page: utf-8 */
|
|
|
1bab02 |
if (!(ntcon->set_console_code_page(65001)))
|
|
|
1bab02 |
return NT_STATUS_NOT_SUPPORTED;
|
|
|
1bab02 |
|
|
|
1bab02 |
if (!(ntcon->set_console_output_code_page(65001)))
|
|
|
1bab02 |
return NT_STATUS_NOT_SUPPORTED;
|
|
|
1bab02 |
|
|
|
1bab02 |
/* input events */
|
|
|
1bab02 |
if (!(ntcon->set_console_mode(
|
|
|
1bab02 |
tctx->hin,
|
|
|
1bab02 |
NT_ENABLE_MOUSE_INPUT
|
|
|
1bab02 |
| NT_ENABLE_WINDOW_INPUT)))
|
|
|
1bab02 |
return NT_STATUS_UNSUCCESSFUL;
|
|
|
1bab02 |
|
|
|
1bab02 |
/* ctrl events */
|
|
|
1bab02 |
if (!(ntcon->set_console_ctrl_handler(
|
|
|
1bab02 |
ptyc_console_ctrl,
|
|
|
1bab02 |
true)))
|
|
|
1bab02 |
return NT_STATUS_UNSUCCESSFUL;
|
|
|
1bab02 |
|
|
|
62462a |
/* cursor info */
|
|
|
62462a |
if (!(ntcon->get_console_cursor_info(
|
|
|
62462a |
tctx->hout,
|
|
|
62462a |
&tctx->cursor_info)))
|
|
|
62462a |
return NT_STATUS_UNSUCCESSFUL;
|
|
|
62462a |
|
|
|
1bab02 |
return NT_STATUS_SUCCESS;
|
|
|
1bab02 |
}
|
|
|
1bab02 |
|
|
|
1bab02 |
int ptyc_alloc_console(struct ptyc_driver_ctx * dctx)
|
|
|
1bab02 |
{
|
|
|
1bab02 |
int32_t status;
|
|
|
1bab02 |
struct ptyc_driver_ctx_impl * ictx;
|
|
|
1bab02 |
struct ptyc_term_ctx * tctx;
|
|
|
1bab02 |
struct ptyc_loop_ctx * lctx;
|
|
|
1bab02 |
|
|
|
1bab02 |
if (!(ictx = ptyc_get_driver_ictx(dctx)))
|
|
|
1bab02 |
return NT_STATUS_INVALID_HANDLE;
|
|
|
1bab02 |
|
|
|
1bab02 |
tctx = &ictx->tctx;
|
|
|
1bab02 |
lctx = &ictx->lctx;
|
|
|
1bab02 |
|
|
|
f7f963 |
tctx->screen_size.x = 512;
|
|
|
f7f963 |
tctx->screen_size.y = 4096;
|
|
|
79c2fe |
tctx->drvflags = ictx->cctx.drvflags;
|
|
|
f7f963 |
|
|
|
1bab02 |
if (!(ntcon->alloc_console()))
|
|
|
1bab02 |
return NT_STATUS_UNSUCCESSFUL;
|
|
|
1bab02 |
|
|
|
1bab02 |
if ((status = ptyc_init_console(tctx)))
|
|
|
1bab02 |
return ptyc_set_status(dctx,status);
|
|
|
1bab02 |
|
|
|
1bab02 |
if ((status = ptyc_create_loop_thread(
|
|
|
1bab02 |
&lctx->treader,
|
|
|
1bab02 |
ictx,ptyc_console_reader)))
|
|
|
1bab02 |
return ptyc_set_status(dctx,status);
|
|
|
1bab02 |
|
|
|
1bab02 |
if ((status = ptyc_create_loop_thread(
|
|
|
1bab02 |
&lctx->twriter,
|
|
|
1bab02 |
ictx,ptyc_console_writer)))
|
|
|
1bab02 |
return ptyc_set_status(dctx,status);
|
|
|
1bab02 |
|
|
|
1bab02 |
if ((status = ptyc_create_loop_thread(
|
|
|
1bab02 |
&lctx->tpoller,
|
|
|
1bab02 |
ictx,ptyc_console_poller)))
|
|
|
1bab02 |
return ptyc_set_status(dctx,status);
|
|
|
1bab02 |
|
|
|
1bab02 |
if (dctx->cctx->drvflags & PTYC_DRIVER_DBG_EVENT)
|
|
|
1bab02 |
if ((status = ptyc_create_loop_thread(
|
|
|
1bab02 |
&lctx->tdbgevent,
|
|
|
1bab02 |
ictx,ptyc_dbg_event)))
|
|
|
1bab02 |
return ptyc_set_status(dctx,status);
|
|
|
1bab02 |
|
|
|
1bab02 |
if (dctx->cctx->drvflags & PTYC_DRIVER_DBG_OVEN)
|
|
|
1bab02 |
if ((status = ptyc_create_loop_thread(
|
|
|
1bab02 |
&lctx->tdbgoven,
|
|
|
1bab02 |
ictx,ptyc_dbg_oven)))
|
|
|
1bab02 |
return ptyc_set_status(dctx,status);
|
|
|
1bab02 |
|
|
|
1bab02 |
if (dctx->cctx->drvflags & PTYC_DRIVER_DBG_RAW)
|
|
|
1bab02 |
if ((status = ptyc_create_loop_thread(
|
|
|
1bab02 |
&lctx->tdbgraw,
|
|
|
1bab02 |
ictx,ptyc_dbg_raw)))
|
|
|
1bab02 |
return ptyc_set_status(dctx,status);
|
|
|
1bab02 |
|
|
|
9cf365 |
if ((status = ptyc_dbg_cat(dctx)))
|
|
|
9cf365 |
return ptyc_set_status(dctx,status);
|
|
|
9cf365 |
|
|
|
1bab02 |
return ptyc_set_status(dctx,NT_STATUS_SUCCESS);
|
|
|
1bab02 |
}
|
|
|
1bab02 |
|
|
|
1bab02 |
|
|
|
1bab02 |
int ptyc_wait_for_console(struct ptyc_driver_ctx * dctx)
|
|
|
1bab02 |
{
|
|
|
1bab02 |
struct ptyc_driver_ctx_impl * ictx;
|
|
|
1bab02 |
|
|
|
1bab02 |
if (!(ictx = ptyc_get_driver_ictx(dctx)))
|
|
|
1bab02 |
return NT_STATUS_INVALID_HANDLE;
|
|
|
1bab02 |
|
|
|
1bab02 |
return ntapi->zw_wait_for_single_object(
|
|
|
1bab02 |
ictx->lctx.tpoller.hthread,
|
|
|
1bab02 |
NT_SYNC_ALERTABLE,0);
|
|
|
1bab02 |
}
|
|
|
1bab02 |
|
|
|
1bab02 |
|
|
|
1bab02 |
void ptyc_free_console(struct ptyc_driver_ctx * dctx)
|
|
|
1bab02 |
{
|
|
|
1bab02 |
struct ptyc_driver_ctx_impl * ictx;
|
|
|
1bab02 |
|
|
|
1bab02 |
if (!(ictx = ptyc_get_driver_ictx(dctx)))
|
|
|
1bab02 |
return;
|
|
|
1bab02 |
|
|
|
1bab02 |
ptyc_free_console_impl(ictx,NT_STATUS_SUCCESS);
|
|
|
1bab02 |
}
|