Blob Blame History Raw
/*********************************************************/
/*  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(&params)))
		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;
}