summaryrefslogtreecommitdiffhomepage
path: root/src/daemon/ntapi_dsr_internal_connection.c
blob: e4407192a687204ff3209a95f6dccf4c1d5aa7f1 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
/********************************************************/
/*  ntapi: Native API core library                      */
/*  Copyright (C) 2013--2017  Z. Gilboa                 */
/*  Released under GPLv2 and GPLv3; see COPYING.NTAPI.  */
/********************************************************/

#include <ntapi/nt_atomic.h>
#include <ntapi/nt_status.h>
#include <ntapi/nt_thread.h>
#include <ntapi/nt_port.h>
#include <ntapi/nt_daemon.h>
#include <ntapi/ntapi.h>
#include "ntapi_impl.h"

int32_t __attr_hidden__ __ntapi_tt_seh_frame(void *, void *, void *, int32_t (*)(nt_daemon_params *));

static int32_t __ntapi_dsr_internal_client_connect_exit(
	nt_daemon_params *	params,
	int32_t			status)
{
	at_store_32(
		&params->exit_code_internal_client,
		status);

	return __ntapi->zw_terminate_thread(
		NT_CURRENT_THREAD_HANDLE,
		status);
}

/* __ntapi_dsr_internal_client_connect executes in its own temporary thread */
static int32_t __ntapi_dsr_internal_client_connect_impl(nt_daemon_params * params)
{
	int32_t				status;
	nt_unicode_string		server_name;
	nt_object_attributes		oa;
	nt_security_quality_of_service	sqos;

	/* init server_name */
	server_name.strlen = (uint16_t)__ntapi->tt_string_null_offset_short((int16_t *)params->port_name);
	server_name.maxlen = 0;
	server_name.buffer = params->port_name;

	/* init security structure */
	sqos.length 			= sizeof(sqos);
	sqos.impersonation_level	= NT_SECURITY_IMPERSONATION;
	sqos.context_tracking_mode	= NT_SECURITY_TRACKING_DYNAMIC;
	sqos.effective_only		= 1;

	/* init the port's object attributes */
	oa.len		= sizeof(oa);
	oa.root_dir	= 0;
	oa.obj_name	= &server_name;
	oa.obj_attr	= 0;
	oa.sec_desc	= params->port_sd;
	oa.sec_qos	= &sqos;

	/* establish internal connection */
	if ((status = __ntapi->zw_connect_port(
			&params->hport_internal_client,
			&server_name,
			&sqos,
			0,0,0,0,0)))
		return __ntapi_dsr_internal_client_connect_exit(
			params,status);

	/* update port info */
	if (params->pport_internal_client)
		at_store(
			(intptr_t *)params->pport_internal_client,
			(intptr_t)params->hport_internal_client);

	/* signal the 'internal-client-is-ready' event */
	status = __ntapi->zw_set_event(
		params->hevent_internal_client_ready,
		0);

	/* exit the task-specific thread */
	return __ntapi_dsr_internal_client_connect_exit(
		params,status);
}

int32_t __ntapi_dsr_internal_client_connect(nt_daemon_params * params)
{
	return __ntapi_tt_seh_frame(
		params,0,0,
		__ntapi_dsr_internal_client_connect_impl);
}

/* __ntapi_dsr_connect_internal_client executes in the daemon's dedicated thread */
int32_t __ntapi_dsr_connect_internal_client(nt_daemon_params * params)
{
	int32_t			status;
	intptr_t		port_id;
	nt_port_message		port_msg;
	void *			hport;

	/* first connection */
	if ((status = __ntapi->zw_reply_wait_receive_port(
			params->hport_daemon,
			&port_id,0,&port_msg)))
		return status;

	/* the internal client must be first */
	if (port_msg.client_id.process_id != pe_get_current_process_id())
		return NT_STATUS_PORT_CONNECTION_REFUSED;

	/* accept connection request */
	if ((status = __ntapi->zw_accept_connect_port(
			&hport,
			port_msg.client_id.process_id,
			(nt_port_message *)&port_msg,
			NT_LPC_ACCEPT_CONNECTION,
			(nt_port_section_write *)0,
			(nt_port_section_read *)0)))
		return status;

	/* finalize connection */
	if ((status = __ntapi->zw_complete_connect_port(hport)))
		return status;

	/* all done */
	return NT_STATUS_SUCCESS;
}