Blame src/daemon/toks_daemon_release.c

c78a06
/*********************************************************/
c78a06
/*  toksvc: a framework-native token broker service      */
c78a06
/*  Copyright (C) 2020  Z. Gilboa                        */
c78a06
/*  Released under GPLv2 and GPLv3; see COPYING.TOKSVC.  */
c78a06
/*********************************************************/
c78a06
c78a06
#include <psxtypes/psxtypes.h>
c78a06
#include <ntapi/ntapi.h>
c78a06
c78a06
#include <toksvc/toksvc.h>
c78a06
#include "toksvc_daemon_impl.h"
c78a06
#include "toksvc_driver_impl.h"
c78a06
c78a06
static void toks_daemon_token_reset(struct toks_token * token)
c78a06
{
c78a06
	token->self        = 0;
c78a06
	token->keys.key[0] = 0;
c78a06
	token->keys.key[1] = 0;
c78a06
	token->keys.key[2] = 0;
c78a06
	token->keys.key[3] = 0;
c78a06
	token->keys.key[4] = 0;
c78a06
	token->keys.key[5] = 0;
c78a06
}
c78a06
d73408
static int32_t toks_daemon_unqueue(struct toks_daemon_ctx * dctx)
d73408
{
681a45
	int                         status;
d73408
	int                         nwaiters;
d73408
	struct toks_waiter *        waiter;
d73408
	nt_tty_port_msg *           msg;
d73408
	nt_tty_port_msg             cmsg;
719840
	void *                      hcaller;
d73408
d73408
	msg      = &dctx->reply;
d73408
	nwaiters = toks_get_driver_nwaiters(dctx->driver_ctx);
d73408
eb8750
	if ((nwaiters == 0) || (dctx->ftokens == 0))
d73408
		return NT_STATUS_SUCCESS;
d73408
681a45
681a45
681a45
	waiter = dctx->waiter_first;
681a45
681a45
	toks_set_driver_nwaiters(
681a45
		dctx->driver_ctx,
681a45
		--nwaiters);
681a45
681a45
	dctx->waiter_first++;
681a45
681a45
	if (dctx->waiter_first == dctx->waiter_cap)
681a45
		dctx->waiter_first = dctx->waiter_base;
681a45
681a45
d73408
3034d1
	if (!waiter->msg.header.msg_id)
3034d1
		return NT_STATUS_CANCELLED;
3034d1
719840
719840
	if ((hcaller = waiter->client.hcaller)) {
719840
		status = ntapi->zw_wait_for_single_object(
719840
			hcaller,
719840
			NT_SYNC_NON_ALERTABLE,
719840
			&(nt_timeout){.quad=0});
719840
719840
		ntapi->zw_close(hcaller);
719840
719840
		switch (status) {
719840
			case NT_STATUS_TIMEOUT:
719840
				break;
719840
719840
			default:
719840
				waiter->msg.header.msg_id = 0;
719840
				return NT_STATUS_REQUEST_ABORTED;
719840
		}
719840
	}
719840
719840
d73408
	ntapi->tt_generic_memcpy(
d73408
		&cmsg,msg,
d73408
		sizeof(*msg));
d73408
d73408
	ntapi->tt_generic_memcpy(
d73408
		msg,&waiter->msg,
d73408
		sizeof(*msg));
d73408
658181
	msg->ttyinfo.exarg  = waiter->client.hprocess;
658181
	msg->ttyinfo.status = toks_daemon_acquire(dctx);
658181
	status              = msg->ttyinfo.status;
d73408
658181
	ntapi->zw_set_event(waiter->client.hevent,0);
658181
	ntapi->zw_close(waiter->client.hevent);
d73408
d73408
	ntapi->tt_generic_memcpy(
d73408
		msg,&cmsg,
d73408
		sizeof(*msg));
d73408
681a45
	return status;
d73408
}
d73408
8f6a66
static int toks_daemon_unqueue_ioctl(struct toks_daemon_ctx * dctx)
8f6a66
{
8f6a66
	int ntokens = toks_get_driver_ntokens(dctx->driver_ctx);
8f6a66
8f6a66
	dctx->opcode = TOKS_DAEMON_RELEASE;
8f6a66
8f6a66
	while (dctx->utokens < ntokens) {
bb0371
		if (toks_get_driver_nwaiters(dctx->driver_ctx) == 0) {
bb0371
			dctx->opcode = TOKS_DAEMON_IOCTL;
8f6a66
			return NT_STATUS_SUCCESS;
bb0371
		}
8f6a66
8f6a66
		toks_daemon_unqueue(dctx);
8f6a66
	}
8f6a66
8f6a66
	dctx->opcode = TOKS_DAEMON_IOCTL;
8f6a66
8f6a66
	return NT_STATUS_SUCCESS;
8f6a66
}
8f6a66
c78a06
int32_t __stdcall toks_daemon_release(struct toks_daemon_ctx * dctx)
c78a06
{
c78a06
	nt_tty_port_msg *           msg;
c78a06
	struct toks_token *         token;
c78a06
	struct toks_token *         toptr;
c78a06
	struct toks_token *         tocap;
c78a06
	uint32_t *                  keys;
c78a06
8f6a66
	if (dctx->opcode == TOKS_DAEMON_IOCTL)
8f6a66
		return toks_daemon_unqueue_ioctl(dctx);
8f6a66
c78a06
	msg   = &dctx->reply;
8b933d
	keys  = msg->syncinfo.ipckeys;
c78a06
c78a06
	toptr = toks_get_driver_tokens(dctx->driver_ctx);
8f6a66
	tocap = &toptr[toks_get_driver_atokens(dctx->driver_ctx)];
c78a06
c78a06
	for (token=0; !token && (toptr
c78a06
		if ((toptr->self)
c78a06
				&& (toptr->keys.key[0] == keys[0])
c78a06
				&& (toptr->keys.key[1] == keys[1])
c78a06
				&& (toptr->keys.key[2] == keys[2])
c78a06
				&& (toptr->keys.key[3] == keys[3])
c78a06
				&& (toptr->keys.key[4] == keys[4])
c78a06
				&& (toptr->keys.key[5] == keys[5]))
c78a06
			token = toptr;
c78a06
c78a06
	if (!token)
c78a06
		return NT_STATUS_INVALID_PARAMETER;
c78a06
971724
	if (--dctx->utokens < toks_get_driver_ntokens(dctx->driver_ctx))
971724
		dctx->ftokens++;
8f6a66
c78a06
	toks_daemon_token_reset(token);
c78a06
c78a06
	ntapi->zw_close(token->client.hinstance);
c78a06
d08823
	ntapi->zw_set_event(
d08823
		token->client.halert,
d08823
		0);
d08823
d73408
	do {
d73408
		(void)0;
d73408
	} while (toks_daemon_unqueue(dctx));
d73408
c78a06
	return NT_STATUS_SUCCESS;
c78a06
}