summaryrefslogtreecommitdiffhomepage
path: root/src/pty/ntapi_pty_fd.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/pty/ntapi_pty_fd.c')
-rw-r--r--src/pty/ntapi_pty_fd.c232
1 files changed, 232 insertions, 0 deletions
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);
+}