/*********************************************************/
/* ptycon: a pty-console bridge */
/* Copyright (C) 2016--2017 SysDeer Technologies, LLC */
/* Released under GPLv2 and GPLv3; see COPYING.PTYCON. */
/*********************************************************/
#include <psxtypes/psxtypes.h>
#include <ntapi/ntapi.h>
#include <ptycon/ptycon.h>
#include "ptycon_daemon_impl.h"
#include "ptycon_driver_impl.h"
#define PTYC_VTBL_ELEMENTS PTYC_DAEMON_OPCODE_CAP - PTYC_DAEMON_OPCODE_BASE
static ptyc_daemon_routine * ptyc_daemon_vtbl[PTYC_VTBL_ELEMENTS] = {
ptyc_daemon_connect,
0,
ptyc_daemon_signal,
0,
0,
0
};
int32_t __stdcall ptyc_daemon_loop(void * ctx)
{
struct ptyc_daemon_ctx * dctx;
nt_rtdata * rtdata;
nt_tty_port_msg inbuf;
nt_tty_port_msg outbuf;
nt_tty_port_msg * request;
nt_tty_port_msg * reply;
intptr_t port_id;
int32_t opcode;
if (ntapi->tt_get_runtime_data(&rtdata,0))
return NT_STATUS_INTERNAL_ERROR;
dctx = (struct ptyc_daemon_ctx *)ctx;
/* init */
request = &inbuf;
ntapi->tt_aligned_block_memset(
request,0,sizeof(*request));
/* get first message */
ntapi->zw_reply_wait_receive_port(
dctx->hport_daemon,
&port_id,
0,(nt_port_message *)request);
/* message loop */
do {
switch (request->header.msg_type) {
case NT_LPC_REQUEST:
case NT_LPC_DATAGRAM:
opcode = request->ttyinfo.opcode;
break;
case NT_LPC_CONNECTION_REQUEST:
opcode = PTYC_DAEMON_CONNECT;
break;
default:
opcode = -1;
break;
}
/* dispatch */
reply = &outbuf;
ntapi->tt_aligned_block_memcpy(
(uintptr_t *)reply,
(uintptr_t *)request,
sizeof(*reply));
reply->header.msg_type = NT_LPC_REPLY;
if ((opcode >= PTYC_DAEMON_OPCODE_BASE) && (opcode < PTYC_DAEMON_OPCODE_CAP)) {
reply->ttyinfo.exarg = (void *)request->header.client_id.process_id;
opcode -= PTYC_DAEMON_OPCODE_BASE;
if (ptyc_daemon_vtbl[opcode])
reply->ttyinfo.status = ptyc_daemon_vtbl[opcode](reply);
else
reply->ttyinfo.status = NT_STATUS_NOT_IMPLEMENTED;
} else {
reply->ttyinfo.exarg = NT_INVALID_HANDLE_VALUE;
reply->ttyinfo.status = NT_STATUS_LPC_INVALID_CONNECTION_USAGE;
}
ntapi->tt_aligned_block_memset(
request,0,sizeof(*request));
reply = reply->ttyinfo.exarg
? &outbuf : 0;
if (!reply)
ntapi->zw_reply_wait_receive_port(
dctx->hport_daemon,
&port_id,
0,&request->header);
else if (reply->header.client_id.process_id == rtdata->cid_self.process_id)
ntapi->zw_reply_wait_receive_port(
dctx->hport_daemon,
&port_id,
&reply->header,
&request->header);
else {
ntapi->zw_reply_port(
dctx->hport_daemon,
&reply->header);
ntapi->zw_reply_wait_receive_port(
dctx->hport_daemon,
&port_id,
0,&request->header);
}
} while (request->header.msg_id);
return NT_STATUS_INTERNAL_ERROR;
}