/*********************************************************/ /* ptycon: a pty-console bridge */ /* Copyright (C) 2016 Z. Gilboa */ /* Released under GPLv2 and GPLv3; see COPYING.PTYCON. */ /*********************************************************/ #include #include #include #include #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 __stdcall 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; }