Blob Blame History Raw
/*********************************************************/
/*  toksvc: a framework-native token broker service      */
/*  Copyright (C) 2020  SysDeer Technologies, LLC        */
/*  Released under GPLv2 and GPLv3; see COPYING.TOKSVC.  */
/*********************************************************/

#include <psxtypes/psxtypes.h>
#include <ntapi/ntapi.h>

#include <toksvc/toksvc.h>
#include "toksvc_driver_impl.h"
#include "toksvc_daemon_impl.h"

static int32_t toks_client_cancel(void * hport)
{
	int32_t			status;
	struct _nt_tty_sync_msg	msg;

	ntapi->tt_aligned_block_memset(
		&msg,0,sizeof(msg));

	msg.header.msg_type	= NT_LPC_NEW_MESSAGE;
	msg.header.data_size	= sizeof(msg.data);
	msg.header.msg_size	= sizeof(msg);
	msg.data.ttyinfo.opcode	= TOKS_DAEMON_CANCEL;

	if ((status = ntapi->zw_request_wait_reply_port(hport,&msg,&msg)))
		return status;

	return msg.data.ttyinfo.status;
}

int32_t toks_client_acquire(struct toks_driver_ctx * dctx)
{
	int32_t			status;
	int32_t			estatus;
	void *			hport;
	struct _nt_tty_sync_msg	msg;
	struct _nt_port_keys *	keys;
	int64_t			millisecs;
	nt_timeout		timeout;
	nt_ebi			syncebi;
	const char *		refstr;
	size_t			reflen;
	void *			hduo[2];

	hport  = toks_get_driver_hservice(dctx);
	keys   = toks_get_driver_keys(dctx);
	refstr = toks_get_driver_refstr(dctx);
	reflen = 0;

	ntapi->tt_aligned_block_memset(
		&msg,0,sizeof(msg));

	msg.header.msg_type	  = NT_LPC_NEW_MESSAGE;
	msg.header.data_size	  = sizeof(msg.data);
	msg.header.msg_size	  = sizeof(msg);
	msg.data.ttyinfo.opcode	  = TOKS_DAEMON_ACQUIRE;
	msg.data.syncinfo.hevent  = toks_get_driver_hevent(dctx);

	if (toks_get_driver_tokpid(dctx)) {
		msg.data.syncinfo.ipcsvc.keys.reserved = toks_get_driver_tokpid(dctx);
		msg.data.syncinfo.ipcsvc.options       = TOKS_OPT_FRAMEWORK_PID;
	} else {
		msg.data.syncinfo.ipcsvc.keys.reserved = toks_get_driver_tsyspid(dctx);
	}

	if (refstr && (reflen = toks_strlen(refstr))) {
		if (reflen > sizeof(msg.data.syncinfo.ipcsvc.keys.key))
			reflen = sizeof(msg.data.syncinfo.ipcsvc.keys.key);

		ntapi->tt_generic_memcpy(
			msg.data.syncinfo.ipcsvc.keys.key,
			refstr,reflen);
	}

	if (!(millisecs = toks_get_driver_timeout(dctx))) {
		msg.data.syncinfo.hevent = 0;

	} else if (millisecs == (-1)) {
		timeout.ulow  = ~(0u);
		timeout.ihigh = ~(0x80000000);

	} else {
		timeout.quad = (-1) * 10 * 1000 * millisecs;
	}

	if ((status = ntapi->zw_request_wait_reply_port(hport,&msg,&msg)))
		return status;

	switch (msg.data.ttyinfo.status) {
		case NT_STATUS_SUCCESS:
			break;

		case NT_STATUS_PENDING:
			hduo[0] = msg.data.syncinfo.hevent;
			hduo[1] = toks_get_driver_hserver(dctx);

			status = ntapi->zw_wait_for_multiple_objects(
				2,hduo,
				NT_WAIT_ANY,
				NT_SYNC_NON_ALERTABLE,
				&timeout);

			estatus = ntapi->zw_query_event(
				msg.data.syncinfo.hevent,
				NT_EVENT_BASIC_INFORMATION,
				&syncebi,sizeof(syncebi),
				&(size_t){0});

			if ((estatus == NT_STATUS_SUCCESS) && syncebi.signal_state)
				status = NT_STATUS_SUCCESS;

			switch (status) {
				case NT_STATUS_SUCCESS:
					break;

				case NT_STATUS_TIMEOUT:
					switch (toks_client_cancel(hport)) {
						case NT_STATUS_NOT_FOUND:
							break;

						default:
							return status;
					}

					break;

				default:
					return NT_STATUS_SYSTEM_PROCESS_TERMINATED;
			}

			break;

		default:
			return msg.data.ttyinfo.status;
	}

	keys->key[0] = msg.data.syncinfo.ipckeys[0];
	keys->key[1] = msg.data.syncinfo.ipckeys[1];
	keys->key[2] = msg.data.syncinfo.ipckeys[2];
	keys->key[3] = msg.data.syncinfo.ipckeys[3];
	keys->key[4] = msg.data.syncinfo.ipckeys[4];
	keys->key[5] = msg.data.syncinfo.ipckeys[5];

	return NT_STATUS_SUCCESS;
}