Blame src/daemon/ntapi_dsr_init.c

dd89bb
/********************************************************/
dd89bb
/*  ntapi: Native API core library                      */
4256e2
/*  Copyright (C) 2013--2016  Z. Gilboa                 */
dd89bb
/*  Released under GPLv2 and GPLv3; see COPYING.NTAPI.  */
dd89bb
/********************************************************/
dd89bb
6c2ba1
#include <ntapi/nt_atomic.h>
dd89bb
#include <ntapi/nt_status.h>
dd89bb
#include <ntapi/nt_thread.h>
dd89bb
#include <ntapi/nt_port.h>
dd89bb
#include <ntapi/nt_daemon.h>
dd89bb
#include <ntapi/ntapi.h>
dd89bb
#include "ntapi_impl.h"
dd89bb
6f3f3f
static int32_t __stdcall __ntapi_dsr_once(nt_daemon_params * params);
dd89bb
dd89bb
int32_t __stdcall __ntapi_dsr_init(nt_daemon_params * params)
dd89bb
{
dd89bb
	int32_t			status;
dd89bb
dd89bb
	nt_thread_params	tparams;
dd89bb
	nt_large_integer	timeout;
dd89bb
6c2ba1
	/* report status */
6c2ba1
	at_store_32(
6c2ba1
		&params->exit_code_daemon_loop,
6c2ba1
		NT_STATUS_PENDING);
6c2ba1
6c2ba1
	at_store_32(
6c2ba1
		&params->exit_code_daemon_start,
6c2ba1
		NT_STATUS_PENDING);
6c2ba1
6c2ba1
	at_store_32(
6c2ba1
		&params->exit_code_internal_client,
6c2ba1
		NT_STATUS_PENDING);
6c2ba1
dd89bb
	/* port_keys */
dd89bb
	if (params->flags & NT_DSR_INIT_GENERATE_KEYS)
dd89bb
		if ((status = __ntapi->tt_port_generate_keys(params->port_keys)))
dd89bb
			return status;
dd89bb
dd89bb
	/* port_name_keys */
dd89bb
	if (params->flags & NT_DSR_INIT_FORMAT_KEYS)
dd89bb
		__ntapi->tt_port_format_keys(
dd89bb
			params->port_keys,
dd89bb
			params->port_name_keys);
dd89bb
dd89bb
	/* 'daemon-is-ready' event */
dd89bb
	if (!params->hevent_daemon_ready) {
dd89bb
		if ((status = __ntapi->tt_create_private_event(
dd89bb
				&params->hevent_daemon_ready,
dd89bb
				NT_NOTIFICATION_EVENT,
dd89bb
				NT_EVENT_NOT_SIGNALED)))
dd89bb
			return status;
dd89bb
dd89bb
		if (params->pevent_daemon_ready)
dd89bb
			*(params->pevent_daemon_ready) = params->hevent_daemon_ready;
dd89bb
	}
dd89bb
dd89bb
	/* 'internal-client-is-ready' event */
dd89bb
	if (!params->hevent_internal_client_ready) {
dd89bb
		if ((status = __ntapi->tt_create_inheritable_event(
dd89bb
				&params->hevent_internal_client_ready,
dd89bb
				NT_NOTIFICATION_EVENT,
dd89bb
				NT_EVENT_NOT_SIGNALED)))
dd89bb
			return status;
dd89bb
dd89bb
		if (params->pevent_internal_client_ready)
dd89bb
			*(params->pevent_internal_client_ready) = params->hevent_internal_client_ready;
dd89bb
	}
dd89bb
dd89bb
	/* daemon dedicated thread: general parameters */
dd89bb
	__ntapi->tt_aligned_block_memset(
dd89bb
		&tparams,0,sizeof(tparams));
dd89bb
dd89bb
	tparams.start = (nt_thread_start_routine *)__ntapi_dsr_start;
dd89bb
	tparams.arg   = params;
dd89bb
dd89bb
	/* daemon dedicated thread: stack parameters (optional) */
dd89bb
	tparams.stack_size_commit	= params->stack_size_commit;
dd89bb
	tparams.stack_size_reserve	= params->stack_size_reserve;
dd89bb
	tparams.stack_info		= params->stack_info;
dd89bb
dd89bb
	/* daemon dedicated thread: create */
dd89bb
	status = __ntapi->tt_create_local_thread(&tparams);
dd89bb
	params->hthread_daemon_loop = tparams.hthread;
dd89bb
	if (status) return status;
dd89bb
d34088
d34088
	/* wait for the server to be ready */
d34088
	timeout.quad = NT_DSR_INIT_MAX_WAIT;
d34088
d34088
	if ((status = __ntapi->zw_wait_for_single_object(
d34088
			params->hevent_daemon_ready,
d34088
			0,&timeout))) {
d34088
		__ntapi->zw_terminate_thread(
d34088
			tparams.hthread,
d34088
			status);
d34088
		return status;
d34088
	}
d34088
d34088
dd89bb
	/* daemon dedicated thread: actual stack size */
dd89bb
	params->stack_size_commit	= tparams.stack_size_commit;
dd89bb
	params->stack_size_reserve	= tparams.stack_size_reserve;
dd89bb
dd89bb
dd89bb
	/* establish internal connection */
dd89bb
	__ntapi->tt_aligned_block_memset(
dd89bb
		&tparams,0,sizeof(tparams));
dd89bb
dd89bb
	tparams.start = (nt_thread_start_routine *)__ntapi_dsr_internal_client_connect;
dd89bb
	tparams.arg   = params;
dd89bb
dd89bb
	status = __ntapi->tt_create_local_thread(&tparams);
dd89bb
	params->hthread_internal_client = tparams.hthread;
dd89bb
	if (status) return status;
dd89bb
dd89bb
	/* wait until the internal connection had been established */
dd89bb
	timeout.quad = NT_DSR_INIT_MAX_WAIT;
dd89bb
dd89bb
	status = __ntapi->zw_wait_for_single_object(
dd89bb
		params->hevent_internal_client_ready,
dd89bb
		0,
dd89bb
		&timeout);
dd89bb
dd89bb
	if (params->flags & NT_DSR_INIT_CLOSE_EVENTS) {
dd89bb
		__ntapi->zw_close(params->hevent_daemon_ready);
dd89bb
		__ntapi->zw_close(params->hevent_internal_client_ready);
dd89bb
	}
dd89bb
dd89bb
	return status;
dd89bb
}
dd89bb
dd89bb
dd89bb
/* __ntapi_dsr_start executes in the daemon's dedicated thread */
6f3f3f
int32_t __stdcall __ntapi_dsr_start_impl(nt_daemon_params * params)
dd89bb
{
6f3f3f
	int32_t status;
6f3f3f
6f3f3f
	if ((status = __ntapi_dsr_once(params)))
6f3f3f
		return status;
6f3f3f
6f3f3f
	if ((status = __ntapi_dsr_create_port(params)))
6f3f3f
		return status;
6f3f3f
6f3f3f
	if ((status = __ntapi_dsr_connect_internal_client(params)))
6f3f3f
		return status;
6f3f3f
6f3f3f
	if ((status = params->daemon_loop_routine(params->daemon_loop_context)))
6f3f3f
		return status;
6f3f3f
6f3f3f
	return NT_STATUS_SUCCESS;
6f3f3f
}
dd89bb
6f3f3f
int32_t __stdcall __ntapi_dsr_start(nt_daemon_params * params)
6f3f3f
{
6c2ba1
	at_store_32(
6c2ba1
		&params->exit_code_daemon_loop,
6c2ba1
		NT_STATUS_MORE_PROCESSING_REQUIRED);
6c2ba1
6f3f3f
	return __ntapi->zw_terminate_thread(
6f3f3f
		NT_CURRENT_THREAD_HANDLE,
6f3f3f
		__ntapi_dsr_start_impl(params));
dd89bb
}
dd89bb
6f3f3f
dd89bb
/* __ntapi_dsr_once executes in the daemon's dedicated thread */
6f3f3f
static int32_t __stdcall __ntapi_dsr_once(nt_daemon_params * params)
dd89bb
{
dd89bb
	int32_t status;
dd89bb
dd89bb
	if (!params->daemon_once_routine)
6f3f3f
		return NT_STATUS_SUCCESS;
dd89bb
6f3f3f
	if ((status = params->daemon_once_routine(params->daemon_loop_context)))
6c2ba1
		at_store_32(
6c2ba1
			&params->exit_code_daemon_start,
6c2ba1
			status);
6f3f3f
6f3f3f
	return status;
dd89bb
}
dd89bb
dd89bb
/* __ntapi_dsr_create_port executes in the daemon's dedicated thread */
6c2ba1
static int32_t __stdcall __ntapi_dsr_create_port_exit(
6c2ba1
	nt_daemon_params *	params,
6c2ba1
	int32_t			status)
6c2ba1
{
6c2ba1
	at_store_32(
6c2ba1
		&params->exit_code_daemon_start,
6c2ba1
		status);
6c2ba1
6c2ba1
	return status;
6c2ba1
}
6c2ba1
dd89bb
int32_t __stdcall __ntapi_dsr_create_port(nt_daemon_params * params)
dd89bb
{
6c2ba1
	int32_t				status;
dd89bb
	nt_object_attributes		oa;
dd89bb
	nt_security_quality_of_service	sqos;
dd89bb
	nt_unicode_string		server_name;
dd89bb
dd89bb
	/* init server_name */
dd89bb
	server_name.strlen = (uint16_t)__ntapi->tt_string_null_offset_short((const int16_t *)params->port_name);
dd89bb
	server_name.maxlen = 0;
dd89bb
	server_name.buffer = (uint16_t *)params->port_name;
dd89bb
dd89bb
	/* init security structure */
dd89bb
	sqos.length 			= sizeof(sqos);
dd89bb
	sqos.impersonation_level	= NT_SECURITY_IMPERSONATION;
dd89bb
	sqos.context_tracking_mode	= NT_SECURITY_TRACKING_DYNAMIC;
dd89bb
	sqos.effective_only		= 1;
dd89bb
dd89bb
	/* init the port's object attributes */
dd89bb
	oa.len		= sizeof(oa);
dd89bb
	oa.root_dir	= (void *)0;
dd89bb
	oa.obj_name	= &server_name;
dd89bb
	oa.obj_attr	= 0;
dd89bb
	oa.sec_desc	= (nt_security_descriptor *)0;
dd89bb
	oa.sec_qos	= &sqo;;
dd89bb
dd89bb
	/* create the port */
6c2ba1
	if ((status = __ntapi->zw_create_port(
6f3f3f
			&params->hport_daemon,
6f3f3f
			&oa,0,(uint32_t)params->port_msg_size,
6f3f3f
			0)))
6c2ba1
		return __ntapi_dsr_create_port_exit(
6c2ba1
			params,status);
dd89bb
dd89bb
	/* return port info */
dd89bb
	if (params->pport_daemon)
6c2ba1
		at_store(
6c2ba1
			(intptr_t *)params->pport_daemon,
6c2ba1
			(intptr_t)params->hport_daemon);
dd89bb
dd89bb
	/* signal the daemon-is-ready event */
6c2ba1
	status = __ntapi->zw_set_event(
dd89bb
		params->hevent_daemon_ready,
dd89bb
		(int32_t *)0);
dd89bb
6c2ba1
	return __ntapi_dsr_create_port_exit(
6c2ba1
		params,status);
dd89bb
}