|
|
dd89bb |
/********************************************************/
|
|
|
dd89bb |
/* ntapi: Native API core library */
|
|
|
dd89bb |
/* Copyright (C) 2013,2014,2015 Z. Gilboa */
|
|
|
dd89bb |
/* Released under GPLv2 and GPLv3; see COPYING.NTAPI. */
|
|
|
dd89bb |
/********************************************************/
|
|
|
dd89bb |
|
|
|
dd89bb |
#include <psxtypes/psxtypes.h>
|
|
|
dd89bb |
#include <ntapi/nt_port.h>
|
|
|
dd89bb |
#include <ntapi/nt_tty.h>
|
|
|
dd89bb |
#include <ntapi/ntapi.h>
|
|
|
dd89bb |
#include "ntapi_impl.h"
|
|
|
dd89bb |
#include "ntapi_pty.h"
|
|
|
dd89bb |
|
|
|
dd89bb |
static int32_t __stdcall __ntapi_pty_open_close(
|
|
|
dd89bb |
nt_pty * pty,
|
|
|
dd89bb |
nt_iosb * iosb,
|
|
|
dd89bb |
int32_t opcode)
|
|
|
dd89bb |
{
|
|
|
dd89bb |
int32_t status;
|
|
|
dd89bb |
nt_pty_fd_msg msg;
|
|
|
dd89bb |
|
|
|
dd89bb |
__ntapi->tt_aligned_block_memset(&msg,0,sizeof(msg));
|
|
|
dd89bb |
|
|
|
dd89bb |
msg.header.msg_type = NT_LPC_NEW_MESSAGE;
|
|
|
dd89bb |
msg.header.data_size = sizeof(msg.data);
|
|
|
dd89bb |
msg.header.msg_size = sizeof(msg);
|
|
|
dd89bb |
msg.data.ttyinfo.opcode = opcode;
|
|
|
dd89bb |
|
|
|
dd89bb |
msg.data.fdinfo.hpty = pty->hpty;
|
|
|
dd89bb |
msg.data.fdinfo.access = pty->access;
|
|
|
dd89bb |
msg.data.fdinfo.flags = pty->flags;
|
|
|
dd89bb |
msg.data.fdinfo.share = pty->share;
|
|
|
dd89bb |
msg.data.fdinfo.options = pty->options;
|
|
|
dd89bb |
|
|
|
dd89bb |
msg.data.fdinfo.luid.high = pty->luid.high;
|
|
|
dd89bb |
msg.data.fdinfo.luid.low = pty->luid.low;
|
|
|
dd89bb |
|
|
|
dd89bb |
__ntapi_tt_guid_copy(
|
|
|
dd89bb |
&msg.data.fdinfo.guid,
|
|
|
dd89bb |
&pty->guid);
|
|
|
dd89bb |
|
|
|
dd89bb |
if ((status = __ntapi->zw_request_wait_reply_port(pty->hport,&msg,&msg)))
|
|
|
dd89bb |
return status;
|
|
|
dd89bb |
else if (msg.data.ttyinfo.status)
|
|
|
dd89bb |
return msg.data.ttyinfo.status;
|
|
|
dd89bb |
|
|
|
dd89bb |
pty->hpty = msg.data.fdinfo.hpty;
|
|
|
dd89bb |
pty->section = msg.data.fdinfo.section;
|
|
|
dd89bb |
pty->section_size = msg.data.fdinfo.section_size;
|
|
|
dd89bb |
pty->luid.high = msg.data.fdinfo.luid.high;
|
|
|
dd89bb |
pty->luid.low = msg.data.fdinfo.luid.low;
|
|
|
dd89bb |
iosb->status = msg.data.ttyinfo.status;
|
|
|
dd89bb |
iosb->info = 0;
|
|
|
dd89bb |
|
|
|
dd89bb |
return NT_STATUS_SUCCESS;
|
|
|
dd89bb |
}
|
|
|
dd89bb |
|
|
|
dd89bb |
|
|
|
dd89bb |
static int32_t __fastcall __ntapi_pty_free(nt_pty * pty)
|
|
|
dd89bb |
{
|
|
|
dd89bb |
void * addr;
|
|
|
dd89bb |
size_t size;
|
|
|
dd89bb |
|
|
|
dd89bb |
/* unmap section */
|
|
|
dd89bb |
if (pty->section_addr)
|
|
|
dd89bb |
__ntapi->zw_unmap_view_of_section(
|
|
|
dd89bb |
NT_CURRENT_PROCESS_HANDLE,
|
|
|
dd89bb |
pty->section_addr);
|
|
|
dd89bb |
|
|
|
dd89bb |
/* free control block */
|
|
|
dd89bb |
addr = pty->addr;
|
|
|
dd89bb |
size = pty->size;
|
|
|
dd89bb |
|
|
|
dd89bb |
return __ntapi->zw_free_virtual_memory(
|
|
|
dd89bb |
NT_CURRENT_PROCESS_HANDLE,
|
|
|
dd89bb |
&addr,
|
|
|
dd89bb |
&size,
|
|
|
dd89bb |
NT_MEM_RELEASE);
|
|
|
dd89bb |
}
|
|
|
dd89bb |
|
|
|
dd89bb |
|
|
|
dd89bb |
static int32_t __fastcall __ntapi_pty_fail(nt_pty * pty,int32_t status)
|
|
|
dd89bb |
{
|
|
|
dd89bb |
__ntapi_pty_free(pty);
|
|
|
dd89bb |
return status;
|
|
|
dd89bb |
}
|
|
|
dd89bb |
|
|
|
dd89bb |
|
|
|
dd89bb |
static int32_t __fastcall __ntapi_pty_alloc(nt_pty ** pty)
|
|
|
dd89bb |
{
|
|
|
dd89bb |
int32_t status;
|
|
|
dd89bb |
nt_pty * ctx;
|
|
|
dd89bb |
size_t ctx_size;
|
|
|
dd89bb |
|
|
|
dd89bb |
/* allocate control block */
|
|
|
dd89bb |
ctx = 0;
|
|
|
dd89bb |
ctx_size = sizeof(nt_pty);
|
|
|
dd89bb |
|
|
|
dd89bb |
if ((status = __ntapi->zw_allocate_virtual_memory(
|
|
|
dd89bb |
NT_CURRENT_PROCESS_HANDLE,
|
|
|
dd89bb |
(void **)&ctx,
|
|
|
dd89bb |
0,&ctx_size,
|
|
|
dd89bb |
NT_MEM_COMMIT,
|
|
|
dd89bb |
NT_PAGE_READWRITE)))
|
|
|
dd89bb |
return status;
|
|
|
dd89bb |
|
|
|
dd89bb |
/* init control block */
|
|
|
dd89bb |
__ntapi->tt_aligned_block_memset(
|
|
|
dd89bb |
ctx,0,ctx_size);
|
|
|
dd89bb |
|
|
|
dd89bb |
ctx->addr = ctx;
|
|
|
dd89bb |
ctx->size = ctx_size;
|
|
|
dd89bb |
|
|
|
dd89bb |
*pty = ctx;
|
|
|
dd89bb |
return NT_STATUS_SUCCESS;
|
|
|
dd89bb |
}
|
|
|
dd89bb |
|
|
|
dd89bb |
static int32_t __ntapi_pty_connect(
|
|
|
dd89bb |
void * hport,
|
|
|
dd89bb |
nt_pty * ctx,
|
|
|
dd89bb |
nt_iosb * iosb)
|
|
|
dd89bb |
{
|
|
|
dd89bb |
int32_t status;
|
|
|
dd89bb |
|
|
|
dd89bb |
ctx->hport = hport
|
|
|
dd89bb |
? hport
|
|
|
dd89bb |
: __ntapi_internals()->hport_tty_session;
|
|
|
dd89bb |
|
|
|
dd89bb |
/* request */
|
|
|
dd89bb |
iosb = iosb ? iosb : &ctx->iosb;
|
|
|
dd89bb |
|
|
|
dd89bb |
if ((status = __ntapi_pty_open_close(ctx,iosb,NT_TTY_PTY_OPEN)))
|
|
|
dd89bb |
return __ntapi_pty_fail(ctx,status);
|
|
|
dd89bb |
|
|
|
dd89bb |
/* map section */
|
|
|
dd89bb |
if ((status = __ntapi->zw_map_view_of_section(
|
|
|
dd89bb |
ctx->section,
|
|
|
dd89bb |
NT_CURRENT_PROCESS_HANDLE,
|
|
|
dd89bb |
&ctx->section_addr,
|
|
|
dd89bb |
0,ctx->section_size,
|
|
|
dd89bb |
0,&ctx->section_size,
|
|
|
dd89bb |
NT_VIEW_UNMAP,0,
|
|
|
dd89bb |
NT_PAGE_READWRITE)))
|
|
|
dd89bb |
return __ntapi_pty_fail(ctx,status);
|
|
|
dd89bb |
|
|
|
dd89bb |
/* assume conforming clients, config for single lock try */
|
|
|
dd89bb |
__ntapi->tt_sync_block_init(&ctx->sync[__PTY_READ],0,0,1,0,0);
|
|
|
dd89bb |
__ntapi->tt_sync_block_init(&ctx->sync[__PTY_WRITE],0,0,1,0,0);
|
|
|
dd89bb |
|
|
|
dd89bb |
return NT_STATUS_SUCCESS;
|
|
|
dd89bb |
}
|
|
|
dd89bb |
|
|
|
dd89bb |
|
|
|
dd89bb |
int32_t __stdcall __ntapi_pty_open(
|
|
|
dd89bb |
void * hport,
|
|
|
dd89bb |
nt_pty ** pty,
|
|
|
dd89bb |
uint32_t desired_access,
|
|
|
dd89bb |
nt_object_attributes* obj_attr,
|
|
|
dd89bb |
nt_iosb * iosb,
|
|
|
dd89bb |
uint32_t share_access,
|
|
|
dd89bb |
uint32_t open_options)
|
|
|
dd89bb |
{
|
|
|
dd89bb |
int32_t status;
|
|
|
dd89bb |
uint32_t hash;
|
|
|
dd89bb |
nt_guid guid;
|
|
|
dd89bb |
nt_uuid_str_utf16 * guid_str;
|
|
|
dd89bb |
nt_pty * ctx;
|
|
|
dd89bb |
|
|
|
dd89bb |
if (!obj_attr || !obj_attr->obj_name || !obj_attr->obj_name->buffer)
|
|
|
dd89bb |
return NT_STATUS_INVALID_PARAMETER;
|
|
|
dd89bb |
|
|
|
dd89bb |
if (obj_attr->obj_name->strlen != __DEVICE_PATH_PREFIX_LEN + sizeof(nt_guid_str_utf16))
|
|
|
dd89bb |
return NT_STATUS_OBJECT_PATH_INVALID;
|
|
|
dd89bb |
|
|
|
dd89bb |
hash = __ntapi->tt_buffer_crc32(
|
|
|
dd89bb |
0,
|
|
|
dd89bb |
obj_attr->obj_name->buffer,
|
|
|
dd89bb |
__DEVICE_PATH_PREFIX_LEN);
|
|
|
dd89bb |
|
|
|
dd89bb |
if (hash != __DEVICE_PATH_PREFIX_HASH)
|
|
|
dd89bb |
return NT_STATUS_OBJECT_PATH_INVALID;
|
|
|
dd89bb |
|
|
|
dd89bb |
guid_str = (nt_uuid_str_utf16 *)
|
|
|
dd89bb |
((uintptr_t)obj_attr->obj_name->buffer + __DEVICE_PATH_PREFIX_LEN);
|
|
|
dd89bb |
|
|
|
dd89bb |
if (__ntapi->tt_utf16_string_to_guid(guid_str,&guid))
|
|
|
dd89bb |
return NT_STATUS_OBJECT_NAME_INVALID;
|
|
|
dd89bb |
|
|
|
dd89bb |
/* control block */
|
|
|
dd89bb |
if ((status = __ntapi_pty_alloc(&ctx)))
|
|
|
dd89bb |
return status;
|
|
|
dd89bb |
|
|
|
dd89bb |
__ntapi_tt_guid_copy(
|
|
|
dd89bb |
&ctx->guid,
|
|
|
dd89bb |
&guid);
|
|
|
dd89bb |
|
|
|
dd89bb |
ctx->access = desired_access;
|
|
|
dd89bb |
ctx->flags = obj_attr->obj_attr;
|
|
|
dd89bb |
ctx->share = share_access;
|
|
|
dd89bb |
ctx->options = open_options;
|
|
|
dd89bb |
|
|
|
dd89bb |
/* pts */
|
|
|
dd89bb |
if (obj_attr->root_dir) {
|
|
|
dd89bb |
ctx->luid.high = ((nt_pty *)obj_attr->root_dir)->luid.high;
|
|
|
dd89bb |
ctx->luid.low = ((nt_pty *)obj_attr->root_dir)->luid.low;
|
|
|
dd89bb |
}
|
|
|
dd89bb |
|
|
|
dd89bb |
if ((status = __ntapi_pty_connect(hport,ctx,iosb)))
|
|
|
dd89bb |
return status;
|
|
|
dd89bb |
|
|
|
dd89bb |
*pty = ctx;
|
|
|
dd89bb |
|
|
|
dd89bb |
return NT_STATUS_SUCCESS;
|
|
|
dd89bb |
}
|
|
|
dd89bb |
|
|
|
efc01e |
int32_t __stdcall __ntapi_pty_inherit(
|
|
|
efc01e |
__in void * hport,
|
|
|
efc01e |
__out nt_pty ** pty,
|
|
|
efc01e |
__in nt_pty_client_info * client_info)
|
|
|
efc01e |
{
|
|
|
efc01e |
int32_t status;
|
|
|
efc01e |
nt_iosb iosb;
|
|
|
efc01e |
nt_pty_inherit_info inherit;
|
|
|
efc01e |
nt_pty * ctx;
|
|
|
efc01e |
|
|
|
efc01e |
inherit.any[0] = client_info->any[0];
|
|
|
efc01e |
inherit.any[1] = client_info->any[1];
|
|
|
efc01e |
inherit.any[2] = client_info->any[2];
|
|
|
efc01e |
inherit.any[3] = client_info->any[3];
|
|
|
efc01e |
|
|
|
efc01e |
if ((status = __ntapi_pty_query(
|
|
|
efc01e |
hport,&iosb,
|
|
|
efc01e |
&inherit,sizeof(inherit),
|
|
|
efc01e |
NT_PTY_INHERIT_INFORMATION)))
|
|
|
efc01e |
return status;
|
|
|
efc01e |
|
|
|
efc01e |
/* control block */
|
|
|
efc01e |
if ((status = __ntapi_pty_alloc(&ctx)))
|
|
|
efc01e |
return status;
|
|
|
efc01e |
|
|
|
efc01e |
__ntapi_tt_guid_copy(
|
|
|
efc01e |
&ctx->guid,
|
|
|
efc01e |
&inherit.guid);
|
|
|
efc01e |
|
|
|
efc01e |
ctx->access = inherit.access;
|
|
|
efc01e |
ctx->flags = inherit.flags;
|
|
|
efc01e |
ctx->share = inherit.share;
|
|
|
efc01e |
ctx->options = inherit.options;
|
|
|
efc01e |
|
|
|
efc01e |
ctx->luid.low = inherit.luid.low;
|
|
|
efc01e |
ctx->luid.high = inherit.luid.high;
|
|
|
efc01e |
|
|
|
efc01e |
if ((status = __ntapi_pty_connect(hport,ctx,&iosb)))
|
|
|
efc01e |
return status;
|
|
|
efc01e |
|
|
|
efc01e |
*pty = ctx;
|
|
|
efc01e |
|
|
|
efc01e |
return NT_STATUS_SUCCESS;
|
|
|
efc01e |
}
|
|
|
efc01e |
|
|
|
dd89bb |
int32_t __stdcall __ntapi_pty_reopen(
|
|
|
dd89bb |
__in void * hport,
|
|
|
dd89bb |
__in nt_pty * pty)
|
|
|
dd89bb |
{
|
|
|
dd89bb |
return __ntapi_pty_connect(hport,pty,0);
|
|
|
dd89bb |
}
|
|
|
dd89bb |
|
|
|
dd89bb |
int32_t __stdcall __ntapi_pty_close(nt_pty * pty)
|
|
|
dd89bb |
{
|
|
|
dd89bb |
if (!pty || (pty->addr != pty))
|
|
|
dd89bb |
return NT_STATUS_INVALID_PARAMETER;
|
|
|
dd89bb |
|
|
|
dd89bb |
__ntapi_pty_open_close(
|
|
|
dd89bb |
pty,&pty->iosb,NT_TTY_PTY_CLOSE);
|
|
|
dd89bb |
|
|
|
dd89bb |
return __ntapi_pty_free(pty);
|
|
|
dd89bb |
}
|