diff options
Diffstat (limited to 'src/debug')
-rw-r--r-- | src/debug/ptyc_dbg_cat.c | 167 |
1 files changed, 167 insertions, 0 deletions
diff --git a/src/debug/ptyc_dbg_cat.c b/src/debug/ptyc_dbg_cat.c new file mode 100644 index 0000000..4e5e63b --- /dev/null +++ b/src/debug/ptyc_dbg_cat.c @@ -0,0 +1,167 @@ +/*********************************************************/ +/* ptycon: a pty-console bridge */ +/* Copyright (C) 2016 Z. Gilboa */ +/* Released under GPLv2 and GPLv3; see COPYING.PTYCON. */ +/*********************************************************/ + +#include <psxtypes/psxtypes.h> +#include <ntcon/ntcon.h> +#include <ntapi/ntapi.h> + +#include <ptycon/ptycon.h> +#include "ptycon_driver_impl.h" + +static int32_t ptyc_open(void ** hfile, void * hat, const char * arg) +{ + int32_t status; + nt_oa oa; + nt_iosb iosb; + nt_unicode_string path; + nt_unicode_conversion_params_utf8_to_utf16 params = {0,0,0,0,0,0,0,0,0}; + wchar16_t buffer[4096]; + wchar16_t * wch; + size_t nbytes; + + /* utf-8 --> utf-16 */ + params.src = (const unsigned char *)arg; + params.src_size_in_bytes= ntapi->tt_string_null_offset_multibyte(arg); + params.dst = buffer; + params.dst_size_in_bytes= sizeof(buffer); + + if ((status = ntapi->uc_convert_unicode_stream_utf8_to_utf16(¶ms))) + return status; + + /* convenience */ + for (wch=buffer, nbytes=params.bytes_written; nbytes; ) { + if (*wch == '/') + *wch = '\\'; + + nbytes -= sizeof(wchar16_t); + wch++; + } + + /* path */ + path.maxlen = 0; + path.strlen = (uint16_t)params.bytes_written; + path.buffer = buffer; + + /* oa */ + oa.len = sizeof(nt_oa); + oa.root_dir = hat; + oa.obj_name = &path; + oa.obj_attr = 0; + oa.sec_desc = 0; + oa.sec_qos = 0; + + /* open */ + return ntapi->zw_open_file( + hfile, + NT_SEC_SYNCHRONIZE | NT_FILE_READ_ATTRIBUTES | NT_FILE_READ_DATA, + &oa,&iosb, + NT_FILE_SHARE_READ | NT_FILE_SHARE_WRITE | NT_FILE_SHARE_DELETE, + NT_FILE_NON_DIRECTORY_FILE | NT_FILE_SYNCHRONOUS_IO_ALERT); +} + +static int32_t ptyc_cat( + struct ptyc_driver_ctx* dctx, + void * hat, + const char * unit, + void * hevent) +{ + int32_t status; + void * hfile; + nt_iosb iosb; + intptr_t nread; + uintptr_t buffer[32768/sizeof(uintptr_t)]; + char * ch; + + if ((status = ptyc_open(&hfile,hat,unit))) + return status; + + status = ntapi->zw_read_file( + hfile, + 0,0,0, + &iosb, + buffer,sizeof(buffer), + 0,0); + + while (status == NT_STATUS_SUCCESS) { + ch = (char *)buffer; + nread = iosb.info; + + for ( ; nread; ) { + status = ntapi->pty_write( + dctx->cctx->hpts, + hevent,0,0, + &iosb, + ch,nread, + 0,0); + + if (status == NT_STATUS_PENDING) + status = ntapi->zw_wait_for_single_object( + hevent,NT_SYNC_ALERTABLE,0); + + if (status || iosb.status) { + ntapi->zw_close(hfile); + return status ? status : iosb.status; + } + + ch += iosb.info; + nread -= iosb.info; + } + + status = ntapi->zw_read_file( + hfile, + 0,0,0, + &iosb, + buffer,sizeof(buffer), + 0,0); + } + + ntapi->zw_close(hfile); + + return (status == NT_STATUS_END_OF_FILE) + ? NT_STATUS_SUCCESS + : status; +} + +int ptyc_dbg_cat(struct ptyc_driver_ctx * dctx) +{ + int32_t status; + void * hevent; + const char ** punit; + nt_rtdata * rtdata; + nt_peb * peb; + void * hat; + + if (!dctx->units[0]) + return 0; + + if ((status = ntapi->tt_create_private_event( + &hevent, + NT_NOTIFICATION_EVENT, + NT_EVENT_NOT_SIGNALED))) + return status; + + if ((status = ntapi->tt_get_runtime_data(&rtdata,0))) + return status; + + if (!(peb = (nt_peb *)pe_get_peb_address())) + return NT_STATUS_INTERNAL_ERROR; + + if (!peb->process_params) + return NT_STATUS_INTERNAL_ERROR; + + hat = rtdata->hcwd + ? rtdata->hcwd + : peb->process_params->cwd_handle; + + for (punit=dctx->units, status=0; *punit && !status; punit++) + status = ptyc_cat( + dctx,hat, + *punit, + hevent); + + ntapi->zw_close(hevent); + return status; +} |