/*********************************************************/ /* ptycon: a pty-console bridge */ /* Copyright (C) 2016--2017 SysDeer Technologies, LLC */ /* Released under GPLv2 and GPLv3; see COPYING.PTYCON. */ /*********************************************************/ #include #include #include #include #include "ptycon_driver_impl.h" 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; uintptr_t nread; uintptr_t buffer[32768/sizeof(uintptr_t)]; char * ch; if ((status = ptyc_open_file(&hfile,hat,unit,true))) 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,(uint32_t)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; }