/********************************************************/ /* ntapi: Native API core library */ /* Copyright (C) 2013--2017 Z. Gilboa */ /* Released under GPLv2 and GPLv3; see COPYING.NTAPI. */ /********************************************************/ #include #include #include #include #include #include #include "ntapi_impl.h" int32_t __ntapi_tt_seh_frame(void *, void *, void *, int32_t (*)(nt_daemon_params *)); static int32_t __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; /* report status */ 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); /* 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); /* 'port-created' event */ 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); } /* '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) at_store( (intptr_t *)params->pevent_daemon_ready, (intptr_t)params->hevent_daemon_ready); } /* 'internal-client-is-ready' event */ 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); } /* memory barrier */ __ntapi->tt_aligned_block_memlock( params, sizeof(*params)); __ntapi->tt_aligned_block_memlock( params->port_name, sizeof(*params->port_name)); /* 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 */ if ((status = __ntapi->tt_create_local_thread(&tparams))) return status; at_store( (intptr_t *)¶ms->hthread_daemon_loop, (intptr_t)tparams.hthread); /* daemon dedicated thread: actual stack size */ params->stack_size_commit = tparams.stack_size_commit; params->stack_size_reserve = tparams.stack_size_reserve; /* wait for the port to be created */ if ((status = __ntapi->zw_wait_for_single_object( params->hevent_daemon_port, NT_SYNC_NON_ALERTABLE,0))) return status; /* overcome potential scheduling bug in recent (10.0) kernel */ while (params->exit_code_daemon_start == NT_STATUS_PENDING) __ntapi->zw_delay_execution( NT_SYNC_NON_ALERTABLE, &(nt_timeout){{0,0}}); /* verify the port's successful creation */ if (at_locked_xadd_32(¶ms->exit_code_daemon_start,0)) return NT_STATUS_PORT_NOT_SET; /* internal connection task-specific thread */ __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); /* wait for the task-specific thread to exit */ if ((status = __ntapi->zw_wait_for_single_object( params->hthread_internal_client, NT_SYNC_NON_ALERTABLE,0))) return status; /* overcome potential scheduling bug in recent (10.0) kernel */ while (params->exit_code_internal_client == NT_STATUS_PENDING) __ntapi->zw_delay_execution( NT_SYNC_NON_ALERTABLE, &(nt_timeout){{0,0}}); /* verify a successful internal connection */ if (at_locked_xadd_32(¶ms->exit_code_internal_client,0)) return params->exit_code_internal_client; /* all_done */ __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;; } /* __ntapi_dsr_start executes in the daemon's dedicated thread */ 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)); } int32_t __stdcall __ntapi_dsr_start(nt_daemon_params * params) { return __ntapi_tt_seh_frame( params,0,0, __ntapi_dsr_start_routine); } /* __ntapi_dsr_once executes in the daemon's dedicated thread */ static int32_t __stdcall __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; } /* __ntapi_dsr_create_port executes in the daemon's dedicated thread */ 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; /* 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; /* create the port */ 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); /* return port info */ if (params->pport_daemon) at_store( (intptr_t *)params->pport_daemon, (intptr_t)params->hport_daemon); /* set status */ at_store_32( ¶ms->exit_code_daemon_start, NT_STATUS_SUCCESS); /* signal the port-created event */ __ntapi->zw_set_event( params->hevent_daemon_port, 0); return NT_STATUS_SUCCESS; }