/********************************************************/
/* ntapi: Native API core library */
/* Copyright (C) 2013--2016 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 __ntapi_tt_seh_frame(void *, void *, void *, int32_t (*)(nt_daemon_params *));
static int32_t __stdcall __ntapi_dsr_internal_client_connect_fail(
nt_daemon_params * params,
int32_t status)
{
at_store_32(
¶ms->exit_code_internal_client,
status);
return __ntapi->zw_terminate_thread(
NT_CURRENT_THREAD_HANDLE,
status);
}
/* __ntapi_dsr_connect_internal_client executes in the daemon's dedicated thread */
int32_t __stdcall __ntapi_dsr_connect_internal_client(nt_daemon_params * params)
{
int32_t status;
intptr_t port_id;
nt_port_message port_msg;
nt_large_integer timeout;
void * hport;
void * hready;
/* avoid out-of-scope use */
hready = params->hthread_internal_client;
/* report state */
at_store_32(
¶ms->exit_code_daemon_start,
NT_STATUS_MORE_PROCESSING_REQUIRED);
/* timeout-enabled first connection */
timeout.quad = NT_DSR_INIT_MAX_WAIT;
if ((status = __ntapi->zw_reply_wait_receive_port_ex(
params->hport_daemon,
&port_id,
(nt_port_message *)0,
(nt_port_message *)&port_msg,
&timeout)))
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;
/* await client thread task completion */
__ntapi->zw_wait_for_single_object(
hready,NT_SYNC_NON_ALERTABLE,0);
/* all done */
return NT_STATUS_SUCCESS;
}
/* __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;
/* report status */
at_store_32(
¶ms->exit_code_internal_client,
NT_STATUS_MORE_PROCESSING_REQUIRED);
/* init server_name */
server_name.strlen = (uint16_t)__ntapi->tt_string_null_offset_short((const int16_t *)params->port_name);
server_name.maxlen = 0;
server_name.buffer = (uint16_t *)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 = (void *)0;
oa.obj_name = &server_name;
oa.obj_attr = 0;
oa.sec_desc = (nt_security_descriptor *)0;
oa.sec_qos = &sqos;
/* establish internal connection */
if ((status = __ntapi->zw_connect_port(
¶ms->hport_internal_client,
&server_name,
&sqos,
0,0,0,0,0)))
return __ntapi_dsr_internal_client_connect_fail(
params,status);
/* update port info */
if (params->pport_internal_client)
at_store(
(intptr_t *)params->pport_internal_client,
(intptr_t)params->hport_internal_client);
/* report status */
at_store_32(
¶ms->exit_code_internal_client,
status);
/* 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->zw_terminate_thread(
NT_CURRENT_THREAD_HANDLE,
status);
}
int32_t __stdcall __ntapi_dsr_internal_client_connect(nt_daemon_params * params)
{
return __ntapi_tt_seh_frame(
params,0,0,
__ntapi_dsr_internal_client_connect_impl);
}