|
|
9cd8e5 |
/*********************************************************/
|
|
|
9cd8e5 |
/* ptycon: a pty-console bridge */
|
|
|
9cd8e5 |
/* Copyright (C) 2016 Z. Gilboa */
|
|
|
9cd8e5 |
/* Released under GPLv2 and GPLv3; see COPYING.PTYCON. */
|
|
|
9cd8e5 |
/*********************************************************/
|
|
|
9cd8e5 |
|
|
|
9cd8e5 |
#include <psxtypes/psxtypes.h>
|
|
|
9cd8e5 |
#include <ntcon/ntcon.h>
|
|
|
9cd8e5 |
#include <ntapi/ntapi.h>
|
|
|
9cd8e5 |
|
|
|
9cd8e5 |
#include <ptycon/ptycon.h>
|
|
|
9cd8e5 |
#include "ptycon_driver_impl.h"
|
|
|
9cd8e5 |
|
|
|
9cd8e5 |
static int32_t __stdcall ptyc_spawn_return(
|
|
|
9cd8e5 |
nt_runtime_data_block * rtblock,
|
|
|
9cd8e5 |
int32_t status)
|
|
|
9cd8e5 |
{
|
|
|
9cd8e5 |
nt_runtime_data * rtdata;
|
|
|
9cd8e5 |
|
|
|
9cd8e5 |
rtdata = (nt_runtime_data *)rtblock;
|
|
|
9cd8e5 |
|
|
|
9cd8e5 |
if (rtdata->hready)
|
|
|
9cd8e5 |
ntapi->zw_close(
|
|
|
9cd8e5 |
rtdata->hready);
|
|
|
9cd8e5 |
|
|
|
9cd8e5 |
ntapi->zw_free_virtual_memory(
|
|
|
9cd8e5 |
NT_CURRENT_PROCESS_HANDLE,
|
|
|
9cd8e5 |
&rtblock->addr,
|
|
|
9cd8e5 |
&rtblock->size,
|
|
|
9cd8e5 |
NT_MEM_RELEASE);
|
|
|
9cd8e5 |
|
|
|
9cd8e5 |
return status;
|
|
|
9cd8e5 |
}
|
|
|
9cd8e5 |
|
|
|
9cd8e5 |
int __stdcall ptyc_spawn(struct ptyc_driver_ctx * dctx)
|
|
|
9cd8e5 |
{
|
|
|
9cd8e5 |
int32_t status;
|
|
|
9cd8e5 |
char * patharg;
|
|
|
9cd8e5 |
void * hchild[2];
|
|
|
9cd8e5 |
nt_create_process_params params;
|
|
|
9cd8e5 |
struct ptyc_driver_ctx_impl * ictx;
|
|
|
9cd8e5 |
struct ptyc_client_ctx * clctx;
|
|
|
9cd8e5 |
nt_tty_session_info session;
|
|
|
9cd8e5 |
nt_runtime_data_block rtblock;
|
|
|
9cd8e5 |
nt_runtime_data * rdata;
|
|
|
9cd8e5 |
nt_rtdata * self;
|
|
|
9cd8e5 |
nt_peb * peb;
|
|
|
9cd8e5 |
void * hat;
|
|
|
9cd8e5 |
void * hfile;
|
|
|
9cd8e5 |
char ** rargv;
|
|
|
9cd8e5 |
char ** renvp;
|
|
|
9cd8e5 |
wchar16_t ** pwarg;
|
|
|
9cd8e5 |
wchar16_t * wch;
|
|
|
9cd8e5 |
nt_unicode_string * imgname;
|
|
|
9cd8e5 |
uint32_t written;
|
|
|
9cd8e5 |
uintptr_t imgbuf[8192/sizeof(uintptr_t)];
|
|
|
9cd8e5 |
|
|
|
9cd8e5 |
/* init */
|
|
|
9cd8e5 |
if (!(ictx = ptyc_get_driver_ictx(dctx)))
|
|
|
9cd8e5 |
return NT_STATUS_INVALID_HANDLE;
|
|
|
9cd8e5 |
|
|
|
9cd8e5 |
if (!dctx->cctx->eargv)
|
|
|
9cd8e5 |
return NT_STATUS_SUCCESS;
|
|
|
9cd8e5 |
|
|
|
9cd8e5 |
if ((status = ntapi->tt_get_runtime_data(&self,0)))
|
|
|
9cd8e5 |
return status;
|
|
|
9cd8e5 |
|
|
|
9cd8e5 |
clctx = &ictx->clctx;
|
|
|
9cd8e5 |
|
|
|
9cd8e5 |
/* hat */
|
|
|
9cd8e5 |
if (!(peb = (nt_peb *)pe_get_peb_address()))
|
|
|
9cd8e5 |
return NT_STATUS_INTERNAL_ERROR;
|
|
|
9cd8e5 |
|
|
|
9cd8e5 |
if (!peb->process_params)
|
|
|
9cd8e5 |
return NT_STATUS_INTERNAL_ERROR;
|
|
|
9cd8e5 |
|
|
|
9cd8e5 |
hat = (dctx->cctx->hroot && (dctx->cctx->eargv[0][0] == '/'))
|
|
|
9cd8e5 |
? dctx->cctx->hroot
|
|
|
9cd8e5 |
: self->hcwd
|
|
|
9cd8e5 |
? self->hcwd
|
|
|
9cd8e5 |
: peb->process_params->cwd_handle;
|
|
|
9cd8e5 |
|
|
|
9cd8e5 |
patharg = (dctx->cctx->eargv[0][0] == '/')
|
|
|
9cd8e5 |
? &dctx->cctx->eargv[0][1]
|
|
|
9cd8e5 |
: &dctx->cctx->eargv[0][0];
|
|
|
9cd8e5 |
|
|
|
9cd8e5 |
/* hfile */
|
|
|
9cd8e5 |
if ((status = ptyc_open_file(&hfile,hat,patharg,true)))
|
|
|
9cd8e5 |
return status;
|
|
|
9cd8e5 |
|
|
|
9cd8e5 |
/* rtblock */
|
|
|
9cd8e5 |
rtblock.addr = 0;
|
|
|
9cd8e5 |
rtblock.size = 0x10000;
|
|
|
9cd8e5 |
rtblock.remote_addr = 0;
|
|
|
9cd8e5 |
rtblock.remote_size = 0;
|
|
|
9cd8e5 |
rtblock.flags = 0;
|
|
|
9cd8e5 |
|
|
|
9cd8e5 |
if ((status = ntapi->zw_allocate_virtual_memory(
|
|
|
9cd8e5 |
self->hprocess_self,
|
|
|
9cd8e5 |
&rtblock.addr,0,
|
|
|
9cd8e5 |
&rtblock.size,
|
|
|
9cd8e5 |
NT_MEM_COMMIT,
|
|
|
9cd8e5 |
NT_PAGE_READWRITE)))
|
|
|
9cd8e5 |
return status;
|
|
|
9cd8e5 |
|
|
|
9cd8e5 |
ntapi->tt_aligned_block_memset(
|
|
|
9cd8e5 |
rtblock.addr,0,rtblock.size);
|
|
|
9cd8e5 |
|
|
|
9cd8e5 |
if ((status = ntapi->zw_query_object(
|
|
|
9cd8e5 |
hfile,
|
|
|
9cd8e5 |
NT_OBJECT_NAME_INFORMATION,
|
|
|
9cd8e5 |
imgbuf,sizeof(imgbuf),
|
|
|
9cd8e5 |
&written)))
|
|
|
9cd8e5 |
return ptyc_spawn_return(
|
|
|
9cd8e5 |
&rtblock,status);
|
|
|
9cd8e5 |
|
|
|
9cd8e5 |
imgname = (nt_unicode_string *)imgbuf;
|
|
|
9cd8e5 |
rdata = (nt_runtime_data *)rtblock.addr;
|
|
|
9cd8e5 |
|
|
|
9cd8e5 |
/* argv, envp */
|
|
|
9cd8e5 |
if ((status = ntapi->tt_array_copy_utf8(
|
|
|
9cd8e5 |
&rdata->argc,
|
|
|
9cd8e5 |
(const char **)dctx->cctx->eargv,
|
|
|
9cd8e5 |
(const char **)self->envp,
|
|
|
9cd8e5 |
0,0,0,
|
|
|
9cd8e5 |
rtblock.addr,
|
|
|
9cd8e5 |
rdata->buffer,
|
|
|
9cd8e5 |
rtblock.size - sizeof(*rdata),
|
|
|
9cd8e5 |
&rtblock.remote_size)))
|
|
|
9cd8e5 |
return ptyc_spawn_return(
|
|
|
9cd8e5 |
&rtblock,status);
|
|
|
9cd8e5 |
|
|
|
9cd8e5 |
rdata->argv = (char **)&((nt_runtime_data *)0)->buffer;
|
|
|
9cd8e5 |
rdata->envp = rdata->argv + rdata->argc + 1;
|
|
|
9cd8e5 |
|
|
|
9cd8e5 |
rdata->wargv = (wchar16_t **)(rdata->buffer + (rtblock.remote_size / sizeof(uintptr_t)) + 1);
|
|
|
9cd8e5 |
rdata->wenvp = rdata->wargv + rdata->argc + 1;
|
|
|
9cd8e5 |
|
|
|
9cd8e5 |
rargv = rdata->argv + ((uintptr_t)rtblock.addr / sizeof(char *));
|
|
|
9cd8e5 |
renvp = rdata->envp + ((uintptr_t)rtblock.addr / sizeof(char *));
|
|
|
9cd8e5 |
|
|
|
9cd8e5 |
pwarg = rdata->wenvp + self->envc + 1;
|
|
|
9cd8e5 |
wch = (wchar16_t *)pwarg;
|
|
|
9cd8e5 |
|
|
|
9cd8e5 |
if ((status = ntapi->tt_array_convert_utf8_to_utf16(
|
|
|
9cd8e5 |
rargv,
|
|
|
9cd8e5 |
rdata->wargv,
|
|
|
9cd8e5 |
rdata,
|
|
|
9cd8e5 |
wch,
|
|
|
9cd8e5 |
rtblock.size - sizeof(wchar16_t)*(wch-(wchar16_t *)rdata->buffer),
|
|
|
9cd8e5 |
&rtblock.remote_size)))
|
|
|
9cd8e5 |
return ptyc_spawn_return(
|
|
|
9cd8e5 |
&rtblock,status);
|
|
|
9cd8e5 |
|
|
|
9cd8e5 |
wch += rtblock.remote_size/sizeof(wchar16_t);
|
|
|
9cd8e5 |
|
|
|
9cd8e5 |
if ((status = ntapi->tt_array_convert_utf8_to_utf16(
|
|
|
9cd8e5 |
renvp,
|
|
|
9cd8e5 |
rdata->wenvp,
|
|
|
9cd8e5 |
rdata,
|
|
|
9cd8e5 |
wch,
|
|
|
9cd8e5 |
rtblock.size - sizeof(wchar16_t)*(wch-(wchar16_t *)rdata->buffer),
|
|
|
9cd8e5 |
&rtblock.remote_size)))
|
|
|
9cd8e5 |
return ptyc_spawn_return(
|
|
|
9cd8e5 |
&rtblock,status);
|
|
|
9cd8e5 |
|
|
|
9cd8e5 |
rdata->wargv -= (uintptr_t)rtblock.addr / sizeof(wchar16_t *);
|
|
|
9cd8e5 |
rdata->wenvp -= (uintptr_t)rtblock.addr / sizeof(wchar16_t *);
|
|
|
9cd8e5 |
|
|
|
9cd8e5 |
/* session */
|
|
|
9cd8e5 |
if ((status = ntapi->tt_create_inheritable_event(
|
|
|
9cd8e5 |
&rdata->hready,
|
|
|
9cd8e5 |
NT_NOTIFICATION_EVENT,
|
|
|
9cd8e5 |
NT_EVENT_NOT_SIGNALED)))
|
|
|
9cd8e5 |
return ptyc_spawn_return(
|
|
|
9cd8e5 |
&rtblock,status);
|
|
|
9cd8e5 |
|
|
|
9cd8e5 |
ntapi->tt_aligned_block_memcpy(
|
|
|
9cd8e5 |
(uintptr_t *)&rdata->cid_parent,
|
|
|
9cd8e5 |
(uintptr_t *)&self->cid_self,
|
|
|
9cd8e5 |
sizeof(nt_cid));
|
|
|
9cd8e5 |
|
|
|
9cd8e5 |
rdata->hroot = dctx->cctx->hroot;
|
|
|
9cd8e5 |
rdata->hcwd = self->hcwd
|
|
|
9cd8e5 |
? self->hcwd
|
|
|
9cd8e5 |
: peb->process_params->cwd_handle;
|
|
|
9cd8e5 |
|
|
|
9cd8e5 |
rdata->srv_keys[0] = self->srv_keys[0];
|
|
|
9cd8e5 |
rdata->srv_keys[1] = self->srv_keys[1];
|
|
|
9cd8e5 |
rdata->srv_keys[2] = self->srv_keys[2];
|
|
|
9cd8e5 |
rdata->srv_keys[3] = self->srv_keys[3];
|
|
|
9cd8e5 |
rdata->srv_keys[4] = self->srv_keys[4];
|
|
|
9cd8e5 |
rdata->srv_keys[5] = self->srv_keys[5];
|
|
|
9cd8e5 |
|
|
|
9cd8e5 |
rdata->hstdin = NT_INVALID_HANDLE_VALUE;
|
|
|
9cd8e5 |
rdata->hstdout = NT_INVALID_HANDLE_VALUE;
|
|
|
9cd8e5 |
rdata->hstderr = NT_INVALID_HANDLE_VALUE;
|
|
|
9cd8e5 |
|
|
|
9cd8e5 |
rdata->stdin_type = NT_FILE_TYPE_PTY;
|
|
|
9cd8e5 |
rdata->stdout_type = NT_FILE_TYPE_PTY;
|
|
|
9cd8e5 |
rdata->stderr_type = NT_FILE_TYPE_PTY;
|
|
|
9cd8e5 |
|
|
|
9cd8e5 |
rdata->ptyany[0] = clctx->clinfo.any[0];
|
|
|
9cd8e5 |
rdata->ptyany[1] = clctx->clinfo.any[1];
|
|
|
9cd8e5 |
rdata->ptyany[2] = clctx->clinfo.any[2];
|
|
|
9cd8e5 |
rdata->ptyany[3] = clctx->clinfo.any[3];
|
|
|
9cd8e5 |
|
|
|
9cd8e5 |
/* params */
|
|
|
9cd8e5 |
ntapi->tt_aligned_block_memset(
|
|
|
9cd8e5 |
¶ms,0,sizeof(params));
|
|
|
9cd8e5 |
|
|
|
9cd8e5 |
params.image_name = imgname->buffer;
|
|
|
9cd8e5 |
params.rtblock = &rtblock;
|
|
|
9cd8e5 |
params.creation_flags_process = NT_PROCESS_CREATE_FLAGS_INHERIT_HANDLES;
|
|
|
9cd8e5 |
params.creation_flags_thread = NT_PROCESS_CREATE_FLAGS_CREATE_THREAD_SUSPENDED;
|
|
|
9cd8e5 |
|
|
|
9cd8e5 |
/* hoppla */
|
|
|
9cd8e5 |
if ((status = ntapi->tt_create_native_process(¶ms)))
|
|
|
9cd8e5 |
return ptyc_spawn_return(
|
|
|
9cd8e5 |
&rtblock,status);
|
|
|
9cd8e5 |
|
|
|
9cd8e5 |
/* clctx */
|
|
|
9cd8e5 |
clctx->hprocess = params.hprocess;
|
|
|
9cd8e5 |
clctx->hthread = params.hthread;
|
|
|
9cd8e5 |
clctx->cid.process_id = params.cid.process_id;
|
|
|
9cd8e5 |
clctx->cid.thread_id = params.cid.thread_id;
|
|
|
9cd8e5 |
|
|
|
9cd8e5 |
if ((status = ntapi->tty_client_process_register(
|
|
|
9cd8e5 |
self->hsession,
|
|
|
9cd8e5 |
params.pbi.unique_process_id,
|
|
|
9cd8e5 |
0,NT_TTY_INHERIT_HANDLES,0)))
|
|
|
9cd8e5 |
ntapi->zw_terminate_process(
|
|
|
9cd8e5 |
params.hprocess,
|
|
|
9cd8e5 |
status);
|
|
|
9cd8e5 |
|
|
|
9cd8e5 |
session.pid = 0;
|
|
|
9cd8e5 |
session.pgid = 0;
|
|
|
9cd8e5 |
session.sid = 0;
|
|
|
9cd8e5 |
session.syspid = params.pbi.unique_process_id;
|
|
|
9cd8e5 |
|
|
|
9cd8e5 |
if ((status = ntapi->tty_client_session_set(0,&session)))
|
|
|
9cd8e5 |
ntapi->zw_terminate_process(
|
|
|
9cd8e5 |
params.hprocess,
|
|
|
9cd8e5 |
status);
|
|
|
9cd8e5 |
|
|
|
9cd8e5 |
if ((status = ntapi->zw_resume_thread(params.hthread,0)))
|
|
|
9cd8e5 |
ntapi->zw_terminate_process(
|
|
|
9cd8e5 |
params.hprocess,
|
|
|
9cd8e5 |
status);
|
|
|
9cd8e5 |
|
|
|
9cd8e5 |
hchild[1] = params.hprocess;
|
|
|
9cd8e5 |
hchild[0] = rdata->hready;
|
|
|
9cd8e5 |
|
|
|
9cd8e5 |
ntapi->zw_wait_for_multiple_objects(
|
|
|
9cd8e5 |
2,hchild,
|
|
|
9cd8e5 |
NT_WAIT_ANY,
|
|
|
9cd8e5 |
NT_SYNC_NON_ALERTABLE,
|
|
|
9cd8e5 |
0);
|
|
|
9cd8e5 |
|
|
|
9cd8e5 |
return ptyc_spawn_return(
|
|
|
9cd8e5 |
&rtblock,status);
|
|
|
9cd8e5 |
}
|