summaryrefslogtreecommitdiffhomepage
path: root/src/pty
diff options
context:
space:
mode:
Diffstat (limited to 'src/pty')
-rw-r--r--src/pty/ntapi_pty_cancel.c46
-rw-r--r--src/pty/ntapi_pty_fd.c232
-rw-r--r--src/pty/ntapi_pty_io.c130
-rw-r--r--src/pty/ntapi_pty_ioctl.c92
-rw-r--r--src/pty/ntapi_pty_query.c64
-rw-r--r--src/pty/ntapi_pty_set.c64
6 files changed, 628 insertions, 0 deletions
diff --git a/src/pty/ntapi_pty_cancel.c b/src/pty/ntapi_pty_cancel.c
new file mode 100644
index 0000000..4bfbb79
--- /dev/null
+++ b/src/pty/ntapi_pty_cancel.c
@@ -0,0 +1,46 @@
+/********************************************************/
+/* ntapi: Native API core library */
+/* Copyright (C) 2013,2014,2015 Z. Gilboa */
+/* Released under GPLv2 and GPLv3; see COPYING.NTAPI. */
+/********************************************************/
+
+#include <psxtypes/psxtypes.h>
+#include <ntapi/nt_port.h>
+#include <ntapi/nt_tty.h>
+#include <ntapi/ntapi.h>
+#include "ntapi_impl.h"
+#include "ntapi_pty.h"
+
+int32_t __stdcall __ntapi_pty_cancel(
+ nt_pty * pty,
+ nt_iosb * iosb)
+{
+ int32_t status;
+ nt_pty_io_msg msg;
+
+ __ntapi->tt_aligned_block_memset(
+ &msg,0,sizeof(msg));
+
+ msg.header.msg_type = NT_LPC_NEW_MESSAGE;
+ msg.header.data_size = sizeof(msg.data);
+ msg.header.msg_size = sizeof(msg);
+ msg.data.ttyinfo.opcode = NT_TTY_PTY_CANCEL;
+
+ msg.data.ioinfo.hpty = pty->hpty;
+ msg.data.ioinfo.luid.high = pty->luid.high;
+ msg.data.ioinfo.luid.low = pty->luid.low;
+
+ __ntapi->tt_guid_copy(
+ &msg.data.ioinfo.guid,
+ &pty->guid);
+
+ if ((status = __ntapi->zw_request_wait_reply_port(pty->hport,&msg,&msg)))
+ return status;
+ else if (msg.data.ttyinfo.status)
+ return msg.data.ttyinfo.status;
+
+ iosb->info = msg.data.ioinfo.iosb.info;
+ iosb->status = msg.data.ioinfo.iosb.status;
+
+ return NT_STATUS_SUCCESS;
+}
diff --git a/src/pty/ntapi_pty_fd.c b/src/pty/ntapi_pty_fd.c
new file mode 100644
index 0000000..ee0b426
--- /dev/null
+++ b/src/pty/ntapi_pty_fd.c
@@ -0,0 +1,232 @@
+/********************************************************/
+/* ntapi: Native API core library */
+/* Copyright (C) 2013,2014,2015 Z. Gilboa */
+/* Released under GPLv2 and GPLv3; see COPYING.NTAPI. */
+/********************************************************/
+
+#include <psxtypes/psxtypes.h>
+#include <ntapi/nt_port.h>
+#include <ntapi/nt_tty.h>
+#include <ntapi/ntapi.h>
+#include "ntapi_impl.h"
+#include "ntapi_pty.h"
+
+static int32_t __stdcall __ntapi_pty_open_close(
+ nt_pty * pty,
+ nt_iosb * iosb,
+ int32_t opcode)
+{
+ int32_t status;
+ nt_pty_fd_msg msg;
+
+ __ntapi->tt_aligned_block_memset(&msg,0,sizeof(msg));
+
+ msg.header.msg_type = NT_LPC_NEW_MESSAGE;
+ msg.header.data_size = sizeof(msg.data);
+ msg.header.msg_size = sizeof(msg);
+ msg.data.ttyinfo.opcode = opcode;
+
+ msg.data.fdinfo.hpty = pty->hpty;
+ msg.data.fdinfo.access = pty->access;
+ msg.data.fdinfo.flags = pty->flags;
+ msg.data.fdinfo.share = pty->share;
+ msg.data.fdinfo.options = pty->options;
+
+ msg.data.fdinfo.luid.high = pty->luid.high;
+ msg.data.fdinfo.luid.low = pty->luid.low;
+
+ __ntapi_tt_guid_copy(
+ &msg.data.fdinfo.guid,
+ &pty->guid);
+
+ if ((status = __ntapi->zw_request_wait_reply_port(pty->hport,&msg,&msg)))
+ return status;
+ else if (msg.data.ttyinfo.status)
+ return msg.data.ttyinfo.status;
+
+ pty->hpty = msg.data.fdinfo.hpty;
+ pty->section = msg.data.fdinfo.section;
+ pty->section_size = msg.data.fdinfo.section_size;
+ pty->luid.high = msg.data.fdinfo.luid.high;
+ pty->luid.low = msg.data.fdinfo.luid.low;
+ iosb->status = msg.data.ttyinfo.status;
+ iosb->info = 0;
+
+ return NT_STATUS_SUCCESS;
+}
+
+
+static int32_t __fastcall __ntapi_pty_free(nt_pty * pty)
+{
+ void * addr;
+ size_t size;
+
+ /* unmap section */
+ if (pty->section_addr)
+ __ntapi->zw_unmap_view_of_section(
+ NT_CURRENT_PROCESS_HANDLE,
+ pty->section_addr);
+
+ /* free control block */
+ addr = pty->addr;
+ size = pty->size;
+
+ return __ntapi->zw_free_virtual_memory(
+ NT_CURRENT_PROCESS_HANDLE,
+ &addr,
+ &size,
+ NT_MEM_RELEASE);
+}
+
+
+static int32_t __fastcall __ntapi_pty_fail(nt_pty * pty,int32_t status)
+{
+ __ntapi_pty_free(pty);
+ return status;
+}
+
+
+static int32_t __fastcall __ntapi_pty_alloc(nt_pty ** pty)
+{
+ int32_t status;
+ nt_pty * ctx;
+ size_t ctx_size;
+
+ /* allocate control block */
+ ctx = 0;
+ ctx_size = sizeof(nt_pty);
+
+ if ((status = __ntapi->zw_allocate_virtual_memory(
+ NT_CURRENT_PROCESS_HANDLE,
+ (void **)&ctx,
+ 0,&ctx_size,
+ NT_MEM_COMMIT,
+ NT_PAGE_READWRITE)))
+ return status;
+
+ /* init control block */
+ __ntapi->tt_aligned_block_memset(
+ ctx,0,ctx_size);
+
+ ctx->addr = ctx;
+ ctx->size = ctx_size;
+
+ *pty = ctx;
+ return NT_STATUS_SUCCESS;
+}
+
+static int32_t __ntapi_pty_connect(
+ void * hport,
+ nt_pty * ctx,
+ nt_iosb * iosb)
+{
+ int32_t status;
+
+ ctx->hport = hport
+ ? hport
+ : __ntapi_internals()->hport_tty_session;
+
+ /* request */
+ iosb = iosb ? iosb : &ctx->iosb;
+
+ if ((status = __ntapi_pty_open_close(ctx,iosb,NT_TTY_PTY_OPEN)))
+ return __ntapi_pty_fail(ctx,status);
+
+ /* map section */
+ if ((status = __ntapi->zw_map_view_of_section(
+ ctx->section,
+ NT_CURRENT_PROCESS_HANDLE,
+ &ctx->section_addr,
+ 0,ctx->section_size,
+ 0,&ctx->section_size,
+ NT_VIEW_UNMAP,0,
+ NT_PAGE_READWRITE)))
+ return __ntapi_pty_fail(ctx,status);
+
+ /* assume conforming clients, config for single lock try */
+ __ntapi->tt_sync_block_init(&ctx->sync[__PTY_READ],0,0,1,0,0);
+ __ntapi->tt_sync_block_init(&ctx->sync[__PTY_WRITE],0,0,1,0,0);
+
+ return NT_STATUS_SUCCESS;
+}
+
+
+int32_t __stdcall __ntapi_pty_open(
+ void * hport,
+ nt_pty ** pty,
+ uint32_t desired_access,
+ nt_object_attributes* obj_attr,
+ nt_iosb * iosb,
+ uint32_t share_access,
+ uint32_t open_options)
+{
+ int32_t status;
+ uint32_t hash;
+ nt_guid guid;
+ nt_uuid_str_utf16 * guid_str;
+ nt_pty * ctx;
+
+ if (!obj_attr || !obj_attr->obj_name || !obj_attr->obj_name->buffer)
+ return NT_STATUS_INVALID_PARAMETER;
+
+ if (obj_attr->obj_name->strlen != __DEVICE_PATH_PREFIX_LEN + sizeof(nt_guid_str_utf16))
+ return NT_STATUS_OBJECT_PATH_INVALID;
+
+ hash = __ntapi->tt_buffer_crc32(
+ 0,
+ obj_attr->obj_name->buffer,
+ __DEVICE_PATH_PREFIX_LEN);
+
+ if (hash != __DEVICE_PATH_PREFIX_HASH)
+ return NT_STATUS_OBJECT_PATH_INVALID;
+
+ guid_str = (nt_uuid_str_utf16 *)
+ ((uintptr_t)obj_attr->obj_name->buffer + __DEVICE_PATH_PREFIX_LEN);
+
+ if (__ntapi->tt_utf16_string_to_guid(guid_str,&guid))
+ return NT_STATUS_OBJECT_NAME_INVALID;
+
+ /* control block */
+ if ((status = __ntapi_pty_alloc(&ctx)))
+ return status;
+
+ __ntapi_tt_guid_copy(
+ &ctx->guid,
+ &guid);
+
+ ctx->access = desired_access;
+ ctx->flags = obj_attr->obj_attr;
+ ctx->share = share_access;
+ ctx->options = open_options;
+
+ /* pts */
+ if (obj_attr->root_dir) {
+ ctx->luid.high = ((nt_pty *)obj_attr->root_dir)->luid.high;
+ ctx->luid.low = ((nt_pty *)obj_attr->root_dir)->luid.low;
+ }
+
+ if ((status = __ntapi_pty_connect(hport,ctx,iosb)))
+ return status;
+
+ *pty = ctx;
+
+ return NT_STATUS_SUCCESS;
+}
+
+int32_t __stdcall __ntapi_pty_reopen(
+ __in void * hport,
+ __in nt_pty * pty)
+{
+ return __ntapi_pty_connect(hport,pty,0);
+}
+
+int32_t __stdcall __ntapi_pty_close(nt_pty * pty)
+{
+ if (!pty || (pty->addr != pty))
+ return NT_STATUS_INVALID_PARAMETER;
+
+ __ntapi_pty_open_close(
+ pty,&pty->iosb,NT_TTY_PTY_CLOSE);
+
+ return __ntapi_pty_free(pty);
+}
diff --git a/src/pty/ntapi_pty_io.c b/src/pty/ntapi_pty_io.c
new file mode 100644
index 0000000..f110371
--- /dev/null
+++ b/src/pty/ntapi_pty_io.c
@@ -0,0 +1,130 @@
+/********************************************************/
+/* ntapi: Native API core library */
+/* Copyright (C) 2013,2014,2015 Z. Gilboa */
+/* Released under GPLv2 and GPLv3; see COPYING.NTAPI. */
+/********************************************************/
+
+#include <psxtypes/psxtypes.h>
+#include <ntapi/nt_port.h>
+#include <ntapi/nt_tty.h>
+#include <ntapi/ntapi.h>
+#include "ntapi_impl.h"
+#include "ntapi_pty.h"
+
+static int32_t __stdcall __ntapi_pty_read_write(
+ nt_pty * pty,
+ void * hevent,
+ nt_io_apc_routine * apc_routine,
+ void * apc_context,
+ nt_iosb * iosb,
+ void * buffer,
+ size_t nbytes,
+ nt_large_integer * offset,
+ uint32_t * key,
+ int32_t opcode)
+{
+ int32_t status;
+ nt_pty_io_msg msg;
+ off_t soffset;
+ int mode;
+
+ mode = opcode - NT_TTY_PTY_READ;
+ soffset = mode * pty->section_size / 2;
+
+ if (offset && offset->quad)
+ return NT_STATUS_INVALID_PARAMETER;
+
+ else if (__ntapi->tt_sync_block_lock(&pty->sync[mode],1,0,0))
+ return NT_STATUS_RESOURCE_NOT_OWNED;
+
+ nbytes = nbytes <= pty->section_size / 2
+ ? nbytes
+ : pty->section_size / 2;
+
+ __ntapi->tt_aligned_block_memset(
+ &msg,0,sizeof(msg));
+
+ msg.header.msg_type = NT_LPC_NEW_MESSAGE;
+ msg.header.data_size = sizeof(msg.data);
+ msg.header.msg_size = sizeof(msg);
+ msg.data.ttyinfo.opcode = opcode;
+
+ msg.data.ioinfo.hpty = pty->hpty;
+ msg.data.ioinfo.hevent = hevent;
+ msg.data.ioinfo.apc_routine = apc_routine;
+ msg.data.ioinfo.apc_context = apc_context;
+ msg.data.ioinfo.key = key ? *key : 0;
+
+ msg.data.ioinfo.luid.high = pty->luid.high;
+ msg.data.ioinfo.luid.low = pty->luid.low;
+
+ msg.data.ioinfo.riosb = iosb;
+ msg.data.ioinfo.raddr = buffer;
+
+ __ntapi->tt_guid_copy(
+ &msg.data.ioinfo.guid,
+ &pty->guid);
+
+ msg.data.ioinfo.nbytes = nbytes;
+ msg.data.ioinfo.offset = soffset;
+
+ if (mode == __PTY_WRITE)
+ __ntapi->tt_generic_memcpy(
+ (char *)pty->section_addr + soffset,
+ (char *)buffer,
+ nbytes);
+
+ if ((status = __ntapi->zw_request_wait_reply_port(pty->hport,&msg,&msg)))
+ return status;
+ else if (msg.data.ttyinfo.status)
+ return msg.data.ttyinfo.status;
+
+ if (mode == __PTY_READ)
+ __ntapi->tt_generic_memcpy(
+ (char *)buffer,
+ (char *)pty->section_addr + soffset,
+ msg.data.ioinfo.iosb.info);
+
+ iosb->info = msg.data.ioinfo.iosb.info;
+ iosb->status = msg.data.ioinfo.iosb.status;
+
+ return NT_STATUS_SUCCESS;
+}
+
+
+int32_t __stdcall __ntapi_pty_read(
+ __in nt_pty * pty,
+ __in void * hevent __optional,
+ __in nt_io_apc_routine * apc_routine __optional,
+ __in void * apc_context __optional,
+ __out nt_iosb * iosb,
+ __out void * buffer,
+ __in uint32_t nbytes,
+ __in nt_large_integer * offset __optional,
+ __in uint32_t * key __optional)
+{
+ return __ntapi_pty_read_write(
+ pty,
+ hevent,apc_routine,apc_context,
+ iosb,buffer,nbytes,offset,key,
+ NT_TTY_PTY_READ);
+}
+
+
+int32_t __stdcall __ntapi_pty_write(
+ __in nt_pty * pty,
+ __in void * hevent __optional,
+ __in nt_io_apc_routine * apc_routine __optional,
+ __in void * apc_context __optional,
+ __out nt_iosb * iosb,
+ __in void * buffer,
+ __in uint32_t nbytes,
+ __in nt_large_integer * offset __optional,
+ __in uint32_t * key __optional)
+{
+ return __ntapi_pty_read_write(
+ pty,
+ hevent,apc_routine,apc_context,
+ iosb,buffer,nbytes,offset,key,
+ NT_TTY_PTY_WRITE);
+}
diff --git a/src/pty/ntapi_pty_ioctl.c b/src/pty/ntapi_pty_ioctl.c
new file mode 100644
index 0000000..f828753
--- /dev/null
+++ b/src/pty/ntapi_pty_ioctl.c
@@ -0,0 +1,92 @@
+/********************************************************/
+/* ntapi: Native API core library */
+/* Copyright (C) 2013,2014,2015 Z. Gilboa */
+/* Released under GPLv2 and GPLv3; see COPYING.NTAPI. */
+/********************************************************/
+
+#include <psxtypes/psxtypes.h>
+#include <ntapi/nt_port.h>
+#include <ntapi/nt_tty.h>
+#include <ntapi/nt_termios.h>
+#include <ntapi/ntapi.h>
+#include "ntapi_impl.h"
+#include "ntapi_pty.h"
+
+int32_t __stdcall __ntapi_pty_ioctl(
+ nt_pty * pty,
+ void * hevent __optional,
+ nt_io_apc_routine * apc_routine __optional,
+ void * apc_context __optional,
+ nt_iosb * iosb,
+ uint32_t ctlcode,
+ void * input_buffer __optional,
+ uint32_t input_buffer_length,
+ void * output_buffer __optional,
+ uint32_t output_buffer_length)
+{
+ int32_t status;
+ nt_pty_sigctl_msg msg;
+ nt_tty_sigctl_info * input;
+ nt_tty_sigctl_info * output;
+
+ if ((uintptr_t)input_buffer % sizeof(uintptr_t))
+ return NT_STATUS_DATATYPE_MISALIGNMENT_ERROR;
+ else if (input_buffer_length != sizeof(nt_tty_sigctl_info))
+ return NT_STATUS_INVALID_BUFFER_SIZE;
+ else if (!output_buffer)
+ return NT_STATUS_ACCESS_DENIED;
+ else if ((uintptr_t)output_buffer % sizeof(uintptr_t))
+ return NT_STATUS_DATATYPE_MISALIGNMENT_ERROR;
+ else if (output_buffer_length < sizeof(nt_tty_sigctl_info))
+ return NT_STATUS_BUFFER_TOO_SMALL;
+
+ input = (nt_tty_sigctl_info *)input_buffer;
+ output = (nt_tty_sigctl_info *)output_buffer;
+
+ __ntapi->tt_aligned_block_memset(
+ &msg,0,sizeof(msg));
+
+ msg.header.msg_type = NT_LPC_NEW_MESSAGE;
+ msg.header.data_size = sizeof(msg.data);
+ msg.header.msg_size = sizeof(msg);
+ msg.data.ttyinfo.opcode = NT_TTY_PTY_IOCTL;
+
+ msg.data.ctlinfo.hpty = pty->hpty;
+ msg.data.ctlinfo.luid.high = pty->luid.high;
+ msg.data.ctlinfo.luid.low = pty->luid.low;
+ msg.data.ctlinfo.ctlcode = ctlcode;
+
+ __ntapi->tt_guid_copy(
+ &msg.data.ctlinfo.guid,
+ &pty->guid);
+
+ msg.data.ctlinfo.ctxarg[0] = input->ctxarg[0];
+ msg.data.ctlinfo.ctxarg[1] = input->ctxarg[1];
+ msg.data.ctlinfo.ctxarg[2] = input->ctxarg[2];
+ msg.data.ctlinfo.ctxarg[3] = input->ctxarg[3];
+
+ __ntapi->tt_generic_memcpy(
+ (char *)&input->terminfo,
+ (char *)&msg.data.ctlinfo.terminfo,
+ sizeof(input->terminfo));
+
+ __ntapi->tt_generic_memcpy(
+ (char *)&input->winsize,
+ (char *)&msg.data.ctlinfo.winsize,
+ sizeof(input->winsize));
+
+ if ((status = __ntapi->zw_request_wait_reply_port(pty->hport,&msg,&msg)))
+ return status;
+ else if (msg.data.ttyinfo.status)
+ return msg.data.ttyinfo.status;
+
+ __ntapi->tt_aligned_block_memcpy(
+ (uintptr_t *)output,
+ (uintptr_t *)&msg.data.ctlinfo,
+ sizeof(*output));
+
+ iosb->info = msg.data.ctlinfo.iosb.info;
+ iosb->status = msg.data.ctlinfo.iosb.status;
+
+ return NT_STATUS_SUCCESS;
+}
diff --git a/src/pty/ntapi_pty_query.c b/src/pty/ntapi_pty_query.c
new file mode 100644
index 0000000..57d31ee
--- /dev/null
+++ b/src/pty/ntapi_pty_query.c
@@ -0,0 +1,64 @@
+/********************************************************/
+/* ntapi: Native API core library */
+/* Copyright (C) 2013,2014,2015 Z. Gilboa */
+/* Released under GPLv2 and GPLv3; see COPYING.NTAPI. */
+/********************************************************/
+
+#include <psxtypes/psxtypes.h>
+#include <ntapi/nt_port.h>
+#include <ntapi/nt_tty.h>
+#include <ntapi/ntapi.h>
+#include "ntapi_impl.h"
+#include "ntapi_pty.h"
+
+int32_t __stdcall __ntapi_pty_query(
+ nt_pty * pty,
+ nt_io_status_block * iosb,
+ void * pty_info,
+ uint32_t pty_info_length,
+ nt_pty_info_class pty_info_class)
+{
+ int32_t status;
+ nt_pty_sigctl_msg msg;
+ uintptr_t * info;
+
+ if ((pty_info_class<NT_PTY_BASIC_INFORMATION) || (pty_info_class>=NT_PTY_INFORMATION_CAP))
+ return NT_STATUS_INVALID_INFO_CLASS;
+ else if (pty_info_class == NT_PTY_BASIC_INFORMATION)
+ return NT_STATUS_NOT_IMPLEMENTED;
+ else if ((pty_info_class == NT_PTY_CLIENT_INFORMATION) && (pty_info_length != sizeof(nt_pty_client_info)))
+ return NT_STATUS_INVALID_PARAMETER;
+
+ __ntapi->tt_aligned_block_memset(
+ &msg,0,sizeof(msg));
+
+ msg.header.msg_type = NT_LPC_NEW_MESSAGE;
+ msg.header.data_size = sizeof(msg.data);
+ msg.header.msg_size = sizeof(msg);
+ msg.data.ttyinfo.opcode = NT_TTY_PTY_QUERY;
+
+ msg.data.ctlinfo.hpty = pty->hpty;
+ msg.data.ctlinfo.luid.high = pty->luid.high;
+ msg.data.ctlinfo.luid.low = pty->luid.low;
+ msg.data.ctlinfo.ctlcode = pty_info_class;
+
+ __ntapi->tt_guid_copy(
+ &msg.data.ctlinfo.guid,
+ &pty->guid);
+
+ if ((status = __ntapi->zw_request_wait_reply_port(pty->hport,&msg,&msg)))
+ return status;
+ else if (msg.data.ttyinfo.status)
+ return msg.data.ttyinfo.status;
+
+ iosb->info = msg.data.ctlinfo.iosb.info;
+ iosb->status = msg.data.ctlinfo.iosb.status;
+
+ info = (uintptr_t *)pty_info;
+ info[0] = msg.data.ctlinfo.ctxarg[0];
+ info[1] = msg.data.ctlinfo.ctxarg[1];
+ info[2] = msg.data.ctlinfo.ctxarg[2];
+ info[3] = msg.data.ctlinfo.ctxarg[3];
+
+ return NT_STATUS_SUCCESS;
+}
diff --git a/src/pty/ntapi_pty_set.c b/src/pty/ntapi_pty_set.c
new file mode 100644
index 0000000..1543e7c
--- /dev/null
+++ b/src/pty/ntapi_pty_set.c
@@ -0,0 +1,64 @@
+/********************************************************/
+/* ntapi: Native API core library */
+/* Copyright (C) 2013,2014,2015 Z. Gilboa */
+/* Released under GPLv2 and GPLv3; see COPYING.NTAPI. */
+/********************************************************/
+
+#include <psxtypes/psxtypes.h>
+#include <ntapi/nt_port.h>
+#include <ntapi/nt_tty.h>
+#include <ntapi/ntapi.h>
+#include "ntapi_impl.h"
+#include "ntapi_pty.h"
+
+int32_t __stdcall __ntapi_pty_set(
+ nt_pty * pty,
+ nt_io_status_block * iosb,
+ void * pty_info,
+ uint32_t pty_info_length,
+ nt_pty_info_class pty_info_class)
+{
+ int32_t status;
+ nt_pty_sigctl_msg msg;
+ uintptr_t * info;
+
+ if ((pty_info_class<NT_PTY_BASIC_INFORMATION) || (pty_info_class>=NT_PTY_INFORMATION_CAP))
+ return NT_STATUS_INVALID_INFO_CLASS;
+ else if (pty_info_class == NT_PTY_BASIC_INFORMATION)
+ return NT_STATUS_NOT_IMPLEMENTED;
+ else if ((pty_info_class == NT_PTY_CLIENT_INFORMATION) && (pty_info_length != sizeof(nt_pty_client_info)))
+ return NT_STATUS_INVALID_PARAMETER;
+
+ __ntapi->tt_aligned_block_memset(
+ &msg,0,sizeof(msg));
+
+ msg.header.msg_type = NT_LPC_NEW_MESSAGE;
+ msg.header.data_size = sizeof(msg.data);
+ msg.header.msg_size = sizeof(msg);
+ msg.data.ttyinfo.opcode = NT_TTY_PTY_SET;
+
+ msg.data.ctlinfo.hpty = pty->hpty;
+ msg.data.ctlinfo.luid.high = pty->luid.high;
+ msg.data.ctlinfo.luid.low = pty->luid.low;
+ msg.data.ctlinfo.ctlcode = pty_info_class;
+
+ __ntapi->tt_guid_copy(
+ &msg.data.ctlinfo.guid,
+ &pty->guid);
+
+ info = (uintptr_t *)pty_info;
+ msg.data.ctlinfo.ctxarg[0] = info[0];
+ msg.data.ctlinfo.ctxarg[1] = info[1];
+ msg.data.ctlinfo.ctxarg[2] = info[2];
+ msg.data.ctlinfo.ctxarg[3] = info[3];
+
+ if ((status = __ntapi->zw_request_wait_reply_port(pty->hport,&msg,&msg)))
+ return status;
+ else if (msg.data.ttyinfo.status)
+ return msg.data.ttyinfo.status;
+
+ iosb->info = msg.data.ctlinfo.iosb.info;
+ iosb->status = msg.data.ctlinfo.iosb.status;
+
+ return NT_STATUS_SUCCESS;
+}