Blame src/console/ptyc_console_alloc.c

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
}