diff options
Diffstat (limited to 'src/daemon')
-rw-r--r-- | src/daemon/ntapi_dsr_init.c | 189 | ||||
-rw-r--r-- | src/daemon/ntapi_dsr_internal_connection.c | 142 |
2 files changed, 331 insertions, 0 deletions
diff --git a/src/daemon/ntapi_dsr_init.c b/src/daemon/ntapi_dsr_init.c new file mode 100644 index 0000000..889de6b --- /dev/null +++ b/src/daemon/ntapi_dsr_init.c @@ -0,0 +1,189 @@ +/********************************************************/ +/* ntapi: Native API core library */ +/* Copyright (C) 2013,2014,2015 Z. Gilboa */ +/* Released under GPLv2 and GPLv3; see COPYING.NTAPI. */ +/********************************************************/ + +#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" + +static void __stdcall __ntapi_dsr_once(nt_daemon_params * params); + +int32_t __stdcall __ntapi_dsr_init(nt_daemon_params * params) +{ + int32_t status; + + nt_thread_params tparams; + nt_large_integer timeout; + + /* port_keys */ + if (params->flags & NT_DSR_INIT_GENERATE_KEYS) + if ((status = __ntapi->tt_port_generate_keys(params->port_keys))) + return status; + + /* port_name_keys */ + if (params->flags & NT_DSR_INIT_FORMAT_KEYS) + __ntapi->tt_port_format_keys( + params->port_keys, + params->port_name_keys); + + /* 'daemon-is-ready' event */ + if (!params->hevent_daemon_ready) { + if ((status = __ntapi->tt_create_private_event( + ¶ms->hevent_daemon_ready, + NT_NOTIFICATION_EVENT, + NT_EVENT_NOT_SIGNALED))) + return status; + + if (params->pevent_daemon_ready) + *(params->pevent_daemon_ready) = params->hevent_daemon_ready; + } + + /* 'internal-client-is-ready' event */ + if (!params->hevent_internal_client_ready) { + if ((status = __ntapi->tt_create_inheritable_event( + ¶ms->hevent_internal_client_ready, + NT_NOTIFICATION_EVENT, + NT_EVENT_NOT_SIGNALED))) + return status; + + if (params->pevent_internal_client_ready) + *(params->pevent_internal_client_ready) = params->hevent_internal_client_ready; + } + + /* daemon dedicated thread: general parameters */ + __ntapi->tt_aligned_block_memset( + &tparams,0,sizeof(tparams)); + + tparams.start = (nt_thread_start_routine *)__ntapi_dsr_start; + tparams.arg = params; + + /* daemon dedicated thread: stack parameters (optional) */ + tparams.stack_size_commit = params->stack_size_commit; + tparams.stack_size_reserve = params->stack_size_reserve; + tparams.stack_info = params->stack_info; + + /* daemon dedicated thread: create */ + status = __ntapi->tt_create_local_thread(&tparams); + params->hthread_daemon_loop = tparams.hthread; + if (status) return status; + + /* daemon dedicated thread: actual stack size */ + params->stack_size_commit = tparams.stack_size_commit; + params->stack_size_reserve = tparams.stack_size_reserve; + + + /* establish internal connection */ + __ntapi->tt_aligned_block_memset( + &tparams,0,sizeof(tparams)); + + tparams.start = (nt_thread_start_routine *)__ntapi_dsr_internal_client_connect; + tparams.arg = params; + + status = __ntapi->tt_create_local_thread(&tparams); + params->hthread_internal_client = tparams.hthread; + if (status) return status; + + /* wait until the internal connection had been established */ + timeout.quad = NT_DSR_INIT_MAX_WAIT; + + status = __ntapi->zw_wait_for_single_object( + params->hevent_internal_client_ready, + 0, + &timeout); + + if (params->flags & NT_DSR_INIT_CLOSE_EVENTS) { + __ntapi->zw_close(params->hevent_daemon_ready); + __ntapi->zw_close(params->hevent_internal_client_ready); + } + + return status; +} + + +/* __ntapi_dsr_start executes in the daemon's dedicated thread */ +int32_t __stdcall __ntapi_dsr_start(nt_daemon_params * params) +{ + __ntapi_dsr_once(params); + __ntapi_dsr_create_port(params); + __ntapi_dsr_connect_internal_client(params); + params->daemon_loop_routine(params->daemon_loop_context); + + /* (no return) */ + return NT_STATUS_INTERNAL_ERROR; +} + +/* __ntapi_dsr_once executes in the daemon's dedicated thread */ +static void __stdcall __ntapi_dsr_once(nt_daemon_params * params) +{ + int32_t status; + + if (!params->daemon_once_routine) + return; + + if ((status = params->daemon_once_routine(params->daemon_loop_context))) { + params->exit_code_daemon_start = status; + __ntapi->zw_terminate_thread(NT_CURRENT_THREAD_HANDLE,status); + } +} + +/* __ntapi_dsr_create_port executes in the daemon's dedicated thread */ +int32_t __stdcall __ntapi_dsr_create_port(nt_daemon_params * params) +{ + int32_t * pstatus; + nt_object_attributes oa; + nt_security_quality_of_service sqos; + nt_unicode_string server_name; + + pstatus = ¶ms->exit_code_daemon_start; + + /* 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; + + /* create the port */ + *pstatus = __ntapi->zw_create_port( + ¶ms->hport_daemon, + &oa,0,(uint32_t)params->port_msg_size, + 0); + + if (*pstatus != NT_STATUS_SUCCESS) + __ntapi->zw_terminate_thread( + NT_CURRENT_THREAD_HANDLE, + *pstatus); + + /* return port info */ + if (params->pport_daemon) + *(params->pport_daemon) = params->hport_daemon; + + /* signal the daemon-is-ready event */ + *pstatus = __ntapi->zw_set_event( + params->hevent_daemon_ready, + (int32_t *)0); + + if (*pstatus != NT_STATUS_SUCCESS) + __ntapi->zw_terminate_thread( + NT_CURRENT_THREAD_HANDLE, + *pstatus); + + return *pstatus; +} diff --git a/src/daemon/ntapi_dsr_internal_connection.c b/src/daemon/ntapi_dsr_internal_connection.c new file mode 100644 index 0000000..7726b3f --- /dev/null +++ b/src/daemon/ntapi_dsr_internal_connection.c @@ -0,0 +1,142 @@ +/********************************************************/ +/* ntapi: Native API core library */ +/* Copyright (C) 2013,2014,2015 Z. Gilboa */ +/* Released under GPLv2 and GPLv3; see COPYING.NTAPI. */ +/********************************************************/ + +#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" + +/* __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 * pstatus; + + intptr_t port_id; + nt_port_message port_msg; + nt_large_integer timeout; + void * _hport_client; + + pstatus = ¶ms->exit_code_daemon_start; + + /* timeout-enabled first connection */ + timeout.quad = NT_DSR_INIT_MAX_WAIT; + + *pstatus = __ntapi->zw_reply_wait_receive_port_ex( + params->hport_daemon, + &port_id, + (nt_port_message *)0, + (nt_port_message *)&port_msg, + &timeout); + + if (*pstatus != NT_STATUS_SUCCESS) + __ntapi->zw_terminate_thread( + NT_CURRENT_THREAD_HANDLE, + *pstatus); + + /* the internal client must be first */ + if (port_msg.client_id.process_id != pe_get_current_process_id()) + __ntapi->zw_terminate_thread( + NT_CURRENT_THREAD_HANDLE, + NT_STATUS_PORT_CONNECTION_REFUSED); + + /* accept connection request */ + *pstatus = __ntapi->zw_accept_connect_port( + &_hport_client, + 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); + + if (*pstatus != NT_STATUS_SUCCESS) + __ntapi->zw_terminate_thread( + NT_CURRENT_THREAD_HANDLE, + *pstatus); + + /* finalize connection */ + *pstatus = __ntapi->zw_complete_connect_port(_hport_client); + + if (*pstatus != NT_STATUS_SUCCESS) + __ntapi->zw_terminate_thread( + NT_CURRENT_THREAD_HANDLE, + *pstatus); + + return *pstatus; +} + + +/* __ntapi_dsr_internal_client_connect executes in its own temporary thread */ +int32_t __stdcall __ntapi_dsr_internal_client_connect(nt_daemon_params * params) +{ + int32_t * pstatus; + + nt_unicode_string server_name; + nt_object_attributes oa; + nt_security_quality_of_service sqos; + nt_large_integer timeout; + + pstatus = ¶ms->exit_code_internal_client; + + /* 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; + + /* wait for the server to be ready */ + timeout.quad = NT_DSR_INIT_MAX_WAIT; + + if ((*pstatus = __ntapi->zw_wait_for_single_object( + params->hevent_daemon_ready, + 0,&timeout))) + __ntapi->zw_terminate_thread( + NT_CURRENT_THREAD_HANDLE, + *pstatus); + + /* establish internal connection */ + *pstatus = __ntapi->zw_connect_port( + ¶ms->hport_internal_client, + &server_name, + &sqos, + 0,0,0,0,0); + + if (*pstatus != NT_STATUS_SUCCESS) + __ntapi->zw_terminate_thread( + NT_CURRENT_THREAD_HANDLE, + *pstatus); + + /* return port info */ + if (params->pport_internal_client) + *(params->pport_internal_client) = params->hport_internal_client; + + /* signal the 'internal-client-is-ready' event */ + *pstatus = __ntapi->zw_set_event( + params->hevent_internal_client_ready, + 0); + + /* exit the task-specific thread */ + __ntapi->zw_terminate_thread( + NT_CURRENT_THREAD_HANDLE, + *pstatus); + + /* (no return) */ + return NT_STATUS_INTERNAL_ERROR; +} |