| |
| |
| |
| |
| |
| |
| #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_once(nt_daemon_params * params); |
| static int32_t __ntapi_dsr_start(nt_daemon_params * params); |
| |
| int32_t __stdcall __ntapi_dsr_init(nt_daemon_params * params) |
| { |
| int32_t status; |
| nt_thread_params tparams; |
| |
| |
| at_store_32( |
| ¶ms->exit_code_daemon_loop, |
| NT_STATUS_PENDING); |
| |
| at_store_32( |
| ¶ms->exit_code_daemon_start, |
| NT_STATUS_PENDING); |
| |
| at_store_32( |
| ¶ms->exit_code_internal_client, |
| NT_STATUS_PENDING); |
| |
| |
| if (params->flags & NT_DSR_INIT_GENERATE_KEYS) |
| if ((status = __ntapi->tt_port_generate_keys(params->port_keys))) |
| return status; |
| |
| |
| if (params->flags & NT_DSR_INIT_FORMAT_KEYS) |
| __ntapi->tt_port_format_keys( |
| params->port_keys, |
| params->port_name_keys); |
| |
| |
| if (!params->hevent_daemon_port) { |
| if ((status = __ntapi->tt_create_private_event( |
| ¶ms->hevent_daemon_port, |
| NT_NOTIFICATION_EVENT, |
| NT_EVENT_NOT_SIGNALED))) |
| return status; |
| |
| if (params->pevent_daemon_port) |
| at_store( |
| (intptr_t *)params->pevent_daemon_port, |
| (intptr_t)params->hevent_daemon_port); |
| } |
| |
| |
| 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) |
| at_store( |
| (intptr_t *)params->pevent_daemon_ready, |
| (intptr_t)params->hevent_daemon_ready); |
| } |
| |
| |
| if (!params->hevent_internal_client_ready) { |
| if ((status = __ntapi->tt_create_private_event( |
| ¶ms->hevent_internal_client_ready, |
| NT_NOTIFICATION_EVENT, |
| NT_EVENT_NOT_SIGNALED))) |
| return status; |
| |
| if (params->pevent_internal_client_ready) |
| at_store( |
| (intptr_t *)params->pevent_internal_client_ready, |
| (intptr_t)params->hevent_internal_client_ready); |
| } |
| |
| |
| __ntapi->tt_aligned_block_memlock( |
| params, |
| sizeof(*params)); |
| |
| __ntapi->tt_aligned_block_memlock( |
| params->port_name, |
| sizeof(*params->port_name)); |
| |
| |
| __ntapi->tt_aligned_block_memset( |
| &tparams,0,sizeof(tparams)); |
| |
| tparams.start = (nt_thread_start_routine *)__ntapi_dsr_start; |
| tparams.arg = params; |
| |
| |
| tparams.stack_size_commit = params->stack_size_commit; |
| tparams.stack_size_reserve = params->stack_size_reserve; |
| tparams.stack_info = params->stack_info; |
| |
| |
| if ((status = __ntapi->tt_create_local_thread(&tparams))) |
| return status; |
| |
| at_store( |
| (intptr_t *)¶ms->hthread_daemon_loop, |
| (intptr_t)tparams.hthread); |
| |
| |
| params->stack_size_commit = tparams.stack_size_commit; |
| params->stack_size_reserve = tparams.stack_size_reserve; |
| |
| |
| if ((status = __ntapi->zw_wait_for_single_object( |
| params->hevent_daemon_port, |
| NT_SYNC_NON_ALERTABLE,0))) |
| return status; |
| |
| |
| while (params->exit_code_daemon_start == NT_STATUS_PENDING) |
| __ntapi->zw_delay_execution( |
| NT_SYNC_NON_ALERTABLE, |
| &(nt_timeout){{0,0}}); |
| |
| |
| if (at_locked_xadd_32(¶ms->exit_code_daemon_start,0)) |
| return NT_STATUS_PORT_NOT_SET; |
| |
| |
| __ntapi->tt_aligned_block_memset( |
| &tparams,0,sizeof(tparams)); |
| |
| tparams.start = (nt_thread_start_routine *)__ntapi_dsr_internal_client_connect; |
| tparams.arg = params; |
| |
| if ((status = __ntapi->tt_create_local_thread(&tparams))) |
| return status; |
| |
| at_store( |
| (intptr_t *)¶ms->hthread_internal_client, |
| (intptr_t)tparams.hthread); |
| |
| |
| if ((status = __ntapi->zw_wait_for_single_object( |
| params->hthread_internal_client, |
| NT_SYNC_NON_ALERTABLE,0))) |
| return status; |
| |
| |
| while (params->exit_code_internal_client == NT_STATUS_PENDING) |
| __ntapi->zw_delay_execution( |
| NT_SYNC_NON_ALERTABLE, |
| &(nt_timeout){{0,0}}); |
| |
| |
| if (at_locked_xadd_32(¶ms->exit_code_internal_client,0)) |
| return params->exit_code_internal_client; |
| |
| |
| __ntapi->zw_set_event( |
| params->hevent_daemon_ready, |
| 0); |
| |
| if (params->flags & NT_DSR_INIT_CLOSE_EVENTS) { |
| __ntapi->zw_close(params->hevent_daemon_port); |
| __ntapi->zw_close(params->hevent_daemon_ready); |
| __ntapi->zw_close(params->hevent_internal_client_ready); |
| } |
| |
| return NT_STATUS_SUCCESS;; |
| } |
| |
| |
| |
| static int32_t __ntapi_dsr_start_impl(nt_daemon_params * params) |
| { |
| int32_t status; |
| void * ctx; |
| int32_t (*loop)(void *); |
| |
| ctx = params->daemon_loop_context; |
| loop = params->daemon_loop_routine; |
| |
| if ((status = __ntapi_dsr_once(params))) |
| return status; |
| |
| if ((status = __ntapi_dsr_create_port(params))) |
| return status; |
| |
| if ((status = __ntapi_dsr_connect_internal_client(params))) |
| return status; |
| |
| if ((status = loop(ctx))) |
| return status; |
| |
| return NT_STATUS_SUCCESS; |
| } |
| |
| static int32_t __ntapi_dsr_start_routine(nt_daemon_params * params) |
| { |
| at_store_32( |
| ¶ms->exit_code_daemon_loop, |
| NT_STATUS_MORE_PROCESSING_REQUIRED); |
| |
| return __ntapi->zw_terminate_thread( |
| NT_CURRENT_THREAD_HANDLE, |
| __ntapi_dsr_start_impl(params)); |
| } |
| |
| static int32_t __ntapi_dsr_start(nt_daemon_params * params) |
| { |
| return __ntapi_tt_seh_frame( |
| params,0,0, |
| __ntapi_dsr_start_routine); |
| } |
| |
| |
| static int32_t __ntapi_dsr_once(nt_daemon_params * params) |
| { |
| int32_t status; |
| |
| if (!params->daemon_once_routine) |
| return NT_STATUS_SUCCESS; |
| |
| if ((status = params->daemon_once_routine(params->daemon_loop_context))) |
| at_store_32( |
| ¶ms->exit_code_daemon_start, |
| status); |
| |
| return status; |
| } |
| |
| |
| static int32_t __stdcall __ntapi_dsr_create_port_exit( |
| nt_daemon_params * params, |
| int32_t status) |
| { |
| at_store_32( |
| ¶ms->exit_code_daemon_start, |
| status); |
| |
| __ntapi->zw_set_event( |
| params->hevent_daemon_port, |
| 0); |
| |
| return status; |
| } |
| |
| int32_t __stdcall __ntapi_dsr_create_port(nt_daemon_params * params) |
| { |
| int32_t status; |
| nt_object_attributes oa; |
| nt_security_quality_of_service sqos; |
| nt_unicode_string 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; |
| |
| |
| sqos.length = sizeof(sqos); |
| sqos.impersonation_level = NT_SECURITY_IMPERSONATION; |
| sqos.context_tracking_mode = NT_SECURITY_TRACKING_DYNAMIC; |
| sqos.effective_only = 1; |
| |
| |
| 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; |
| |
| |
| if ((status = __ntapi->zw_create_port( |
| ¶ms->hport_daemon, |
| &oa,0,(uint32_t)params->port_msg_size, |
| 0))) |
| return __ntapi_dsr_create_port_exit( |
| params,status); |
| |
| |
| if (params->pport_daemon) |
| at_store( |
| (intptr_t *)params->pport_daemon, |
| (intptr_t)params->hport_daemon); |
| |
| |
| at_store_32( |
| ¶ms->exit_code_daemon_start, |
| NT_STATUS_SUCCESS); |
| |
| |
| __ntapi->zw_set_event( |
| params->hevent_daemon_port, |
| 0); |
| |
| return NT_STATUS_SUCCESS; |
| } |