/********************************************************/
/* ntapi: Native API core library */
/* Copyright (C) 2013--2016 Z. Gilboa */
/* Released under GPLv2 and GPLv3; see COPYING.NTAPI. */
/********************************************************/
#include <psxtypes/psxtypes.h>
#include <pemagine/pemagine.h>
#include <ntapi/nt_status.h>
#include <ntapi/nt_object.h>
#include <ntapi/nt_thread.h>
#include <ntapi/nt_process.h>
#include <ntapi/nt_string.h>
#include <ntapi/ntapi.h>
#include "ntapi_impl.h"
static int32_t __tt_create_process_cancel(nt_create_process_params * params, int32_t status)
{
if (params->hprocess) {
__ntapi->zw_terminate_process(params->hprocess,NT_STATUS_INTERNAL_ERROR);
__ntapi->zw_close(params->hprocess);
}
if (params->hthread)
__ntapi->zw_close(params->hthread);
return status;
}
int32_t __stdcall __ntapi_tt_create_native_process_v2(
__in_out nt_create_process_params * params)
{
int32_t status;
nt_object_attributes oa_process;
nt_object_attributes oa_thread;
nt_unicode_string nt_image;
nt_unicode_string nt_cmd_line;
wchar16_t * cmd_line_runtime_buffer;
size_t cmd_line_runtime_buffer_size;
nt_create_process_info nt_process_info;
int fresume_thread;
struct {
size_t size_in_bytes;
nt_create_process_ext_param file_info;
} ext_params;
#if defined (__NT32)
wchar16_t runtime_arg[12] = {
' ','-','r',' ',
'i','n','t','e','g','r','a','l'};
#elif defined (__NT64)
wchar16_t runtime_arg[20] = {
' ','-','r',' ',
'i','n','t','e','g','r','a','l',
'-','r','u','n','t','i','m','e'};
#endif
/* validation */
if (params->cmd_line && params->process_params)
return NT_STATUS_INVALID_PARAMETER_MIX;
else if (params->cmd_line && params->rtblock)
return NT_STATUS_INVALID_PARAMETER_MIX;
else if (params->environment && params->process_params)
return NT_STATUS_INVALID_PARAMETER_MIX;
/* image_name */
__ntapi->rtl_init_unicode_string(
&nt_image,
params->image_name);
/* oa_process */
if (!params->obj_attr_process) {
__ntapi->tt_aligned_block_memset(
&oa_process,0,sizeof(oa_process));
oa_process.len = sizeof(oa_process);
params->obj_attr_process = &oa_process;
}
/* oa_thread */
if (!params->obj_attr_thread) {
__ntapi->tt_aligned_block_memset(
&oa_thread,0,sizeof(oa_thread));
oa_thread.len = sizeof(oa_thread);
params->obj_attr_thread = &oa_thread;
}
/* process_params */
if (!params->process_params) {
/* cmd_line */
if (!params->cmd_line) {
params->cmd_line = params->image_name;
}
__ntapi->rtl_init_unicode_string(
&nt_cmd_line,
params->cmd_line);
/* rtdata (alternative to cmd_line) */
if (params->rtblock) {
cmd_line_runtime_buffer = (wchar16_t *)0;
cmd_line_runtime_buffer_size = nt_cmd_line.maxlen
+ sizeof(runtime_arg);
if ((status = __ntapi->zw_allocate_virtual_memory(
NT_CURRENT_PROCESS_HANDLE,
(void **)&cmd_line_runtime_buffer,
0,&cmd_line_runtime_buffer_size,
NT_MEM_RESERVE | NT_MEM_COMMIT,
NT_PAGE_READWRITE)))
return status;
__ntapi->tt_memcpy_utf16(
(wchar16_t *)cmd_line_runtime_buffer,
(wchar16_t *)nt_cmd_line.buffer,
nt_cmd_line.strlen);
__ntapi->tt_memcpy_utf16(
(wchar16_t *)pe_va_from_rva(
cmd_line_runtime_buffer,
nt_cmd_line.strlen),
(wchar16_t *)runtime_arg,
sizeof(runtime_arg));
nt_cmd_line.strlen += sizeof(runtime_arg);
nt_cmd_line.maxlen += sizeof(runtime_arg);
nt_cmd_line.buffer = cmd_line_runtime_buffer;
}
/* environment */
if (!params->environment)
params->environment = __ntapi->tt_get_peb_env_block_utf16();
if ((status = __ntapi->rtl_create_process_parameters(
¶ms->process_params,
&nt_image,
(nt_unicode_string *)0,
(nt_unicode_string *)0,
&nt_cmd_line,
params->environment,
(nt_unicode_string *)0,
(nt_unicode_string *)0,
(nt_unicode_string *)0,
(nt_unicode_string *)0)))
return status;
__ntapi->rtl_normalize_process_params(params->process_params);
}
/* create_process_info */
if (!params->create_process_info) {
__ntapi->tt_aligned_block_memset(
&nt_process_info,0,sizeof(nt_process_info));
nt_process_info.size = sizeof(nt_create_process_info);
nt_process_info.state = NT_PROCESS_CREATE_INITIAL_STATE;
nt_process_info.init_state.init_flags = NT_PROCESS_CREATE_INFO_OBTAIN_OUTPUT;
nt_process_info.init_state.file_access_ext = NT_FILE_READ_ATTRIBUTES|NT_FILE_READ_ACCESS;
params->create_process_info = &nt_process_info;
}
/* create_process_ext_params */
if (!params->create_process_ext_params) {
__ntapi->tt_aligned_block_memset(
&ext_params,0,sizeof(ext_params));
ext_params.size_in_bytes = sizeof(ext_params);
/* file_info */
ext_params.file_info.ext_param_type = NT_CREATE_PROCESS_EXT_PARAM_SET_FILE_NAME;
ext_params.file_info.ext_param_size = nt_image.strlen;
ext_params.file_info.ext_param_addr = nt_image.buffer;
params->create_process_ext_params = (nt_create_process_ext_params *)&ext_params;
}
params->hprocess = 0;
params->hthread = 0;
fresume_thread = 0;
if (params->rtblock) {
fresume_thread = (params->creation_flags_thread ^ 0x01) & 0x01;
params->creation_flags_thread |= 0x01;
}
if (!params->desired_access_process)
params->desired_access_process = NT_PROCESS_ALL_ACCESS;
if (!params->desired_access_thread)
params->desired_access_thread = NT_THREAD_ALL_ACCESS;
if ((status = __ntapi->zw_create_user_process(
¶ms->hprocess,
¶ms->hthread,
params->desired_access_process,
params->desired_access_thread,
params->obj_attr_process,
params->obj_attr_thread,
params->creation_flags_process,
params->creation_flags_thread,
params->process_params,
params->create_process_info,
params->create_process_ext_params)))
return status;
/* tidy up */
__ntapi->zw_close(params->create_process_info->success_state.hfile);
__ntapi->zw_close(params->create_process_info->success_state.hsection);
if ((status = __ntapi->zw_query_information_process(
params->hprocess,
NT_PROCESS_BASIC_INFORMATION,
¶ms->pbi,sizeof(params->pbi),
0)))
return __tt_create_process_cancel(params,status);
if (!params->rtblock)
return NT_STATUS_SUCCESS;
/* rtdata */
if ((status = __ntapi_tt_create_remote_runtime_data(params->hprocess,params->rtblock)))
return __tt_create_process_cancel(params,status);
/* conditional resume */
if (fresume_thread && (status = __ntapi->zw_resume_thread(params->hthread,0)))
return __tt_create_process_cancel(params,status);
return NT_STATUS_SUCCESS;
}