Blob Blame History Raw
/*********************************************************/
/*  ptycon: a pty-console bridge                         */
/*  Copyright (C) 2016--2017  SysDeer Technologies, LLC  */
/*  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_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;
}