Blame src/internal/ntapi.c

dd89bb
/********************************************************/
dd89bb
/*  ntapi: Native API core library                      */
4256e2
/*  Copyright (C) 2013--2016  Z. Gilboa                 */
dd89bb
/*  Released under GPLv2 and GPLv3; see COPYING.NTAPI.  */
dd89bb
/********************************************************/
dd89bb
dd89bb
#include <psxtypes/psxtypes.h>
dd89bb
#include <pemagine/pemagine.h>
dd89bb
dd89bb
#include <ntapi/nt_status.h>
dd89bb
#include <ntapi/nt_crc32.h>
dd89bb
#include <ntapi/nt_object.h>
dd89bb
#include <ntapi/nt_sysinfo.h>
dd89bb
#include <ntapi/nt_memory.h>
dd89bb
#include <ntapi/nt_section.h>
dd89bb
#include <ntapi/nt_thread.h>
dd89bb
#include <ntapi/nt_process.h>
dd89bb
#include <ntapi/nt_job.h>
dd89bb
#include <ntapi/nt_token.h>
dd89bb
#include <ntapi/nt_sync.h>
dd89bb
#include <ntapi/nt_time.h>
dd89bb
#include <ntapi/nt_profiling.h>
dd89bb
#include <ntapi/nt_port.h>
dd89bb
#include <ntapi/nt_device.h>
dd89bb
#include <ntapi/nt_file.h>
dd89bb
#include <ntapi/nt_registry.h>
dd89bb
#include <ntapi/nt_security.h>
dd89bb
#include <ntapi/nt_pnp.h>
dd89bb
#include <ntapi/nt_exception.h>
dd89bb
#include <ntapi/nt_locale.h>
dd89bb
#include <ntapi/nt_uuid.h>
dd89bb
#include <ntapi/nt_atom.h>
dd89bb
#include <ntapi/nt_os.h>
dd89bb
#include <ntapi/nt_ldr.h>
dd89bb
#include <ntapi/nt_string.h>
dd89bb
#include <ntapi/nt_guid.h>
dd89bb
#include <ntapi/nt_argv.h>
dd89bb
#include <ntapi/nt_blitter.h>
dd89bb
#include <ntapi/nt_unicode.h>
dd89bb
#include <ntapi/nt_socket.h>
dd89bb
#include <ntapi/nt_mount.h>
dd89bb
#include <ntapi/nt_istat.h>
dd89bb
#include <ntapi/nt_stat.h>
dd89bb
#include <ntapi/nt_statfs.h>
dd89bb
#include <ntapi/nt_daemon.h>
dd89bb
#include <ntapi/nt_tty.h>
dd89bb
#include <ntapi/nt_vmount.h>
dd89bb
#include <ntapi/nt_hash.h>
dd89bb
#include <ntapi/nt_debug.h>
dd89bb
#include <ntapi/nt_atomic.h>
dd89bb
#include <ntapi/ntapi.h>
dd89bb
dd89bb
#include "ntapi_impl.h"
dd89bb
#include "ntapi_hash_table.h"
dd89bb
dd89bb
/* simplified once mechanism for free-standing applications */
dd89bb
typedef int32_t __fastcall __ntapi_init_fn(ntapi_vtbl ** pvtbl);
dd89bb
dd89bb
static __ntapi_init_fn __ntapi_init_once;
dd89bb
static __ntapi_init_fn __ntapi_init_pending;
dd89bb
static __ntapi_init_fn __ntapi_init_completed;
dd89bb
dd89bb
static intptr_t		 __ntapi_init_idx = 0;
dd89bb
static __ntapi_init_fn * __ntapi_init_vtbl[3] = {
dd89bb
	__ntapi_init_once,
dd89bb
	__ntapi_init_pending,
dd89bb
	__ntapi_init_completed};
dd89bb
dd89bb
/* accessor */
1219be
ntapi_vtbl ___ntapi;
1219be
ntapi_vtbl ___ntapi_shadow;
dd89bb
dd89bb
/* .bss */
dd89bb
static __ntapi_img_sec_bss __ntapi_img_bss;
dd89bb
dd89bb
/* .rdata */
dd89bb
static union __ntapi_img_rdata __ntapi_rdata = {{
dd89bb
		{__NTAPI_HASH_TABLE},		/* __ntapi_import_table */
dd89bb
		0,				/* __ntapi */
1219be
		{				/* __session_name */
1219be
			{0},0,{0},
1219be
			{0,{0},0},
1219be
			{{0},0,{0},0,{0},0,{0},0,{0},0,{0}},
1219be
			0},
1219be
		0}};
dd89bb
dd89bb
#define internals	__ntapi_rdata.img_sec_data.__internals
dd89bb
#define import_table	__ntapi_rdata.img_sec_data.__ntapi_import_table
dd89bb
dd89bb
dd89bb
static int32_t __fastcall __ntapi_init_once(ntapi_vtbl ** pvtbl)
dd89bb
{
dd89bb
	int32_t					status;
dd89bb
	void * 					hntdll;
dd89bb
	size_t					block_size;
dd89bb
	ntapi_zw_allocate_virtual_memory *	pfn_zw_allocate_virtual_memory;
fc3ec7
	char					fname_allocate_virtual_memory[] =
fc3ec7
							"ZwAllocateVirtualMemory";
dd89bb
	/* once */
dd89bb
	at_locked_inc(&__ntapi_init_idx);
dd89bb
dd89bb
	/* pvtbl */
dd89bb
	if (!(pvtbl))
dd89bb
		return NT_STATUS_INVALID_PARAMETER;
dd89bb
	else
dd89bb
		*pvtbl = (ntapi_vtbl *)0;
dd89bb
dd89bb
	/* ntdll */
dd89bb
	if (!(hntdll = pe_get_ntdll_module_handle()))
dd89bb
		return NT_STATUS_DLL_INIT_FAILED;
dd89bb
dd89bb
	pfn_zw_allocate_virtual_memory	= (ntapi_zw_allocate_virtual_memory *)
dd89bb
		pe_get_procedure_address(
dd89bb
			hntdll,
dd89bb
			fname_allocate_virtual_memory);
dd89bb
dd89bb
	if (!pfn_zw_allocate_virtual_memory)
dd89bb
		return NT_STATUS_DLL_INIT_FAILED;
dd89bb
dd89bb
	/* ntapi_internals: alloc */
dd89bb
	block_size = sizeof(ntapi_internals);
dd89bb
	status = pfn_zw_allocate_virtual_memory(
dd89bb
		NT_CURRENT_PROCESS_HANDLE,
dd89bb
		(void **)&internals,
dd89bb
		0,
dd89bb
		&block_size,
dd89bb
		NT_MEM_COMMIT,
dd89bb
		NT_PAGE_READWRITE);
dd89bb
dd89bb
	if (status != NT_STATUS_SUCCESS)
dd89bb
		return status;
dd89bb
dd89bb
	/* hashed import table */
dd89bb
	__ntapi_tt_populate_hashed_import_table(
dd89bb
		pe_get_ntdll_module_handle(),
dd89bb
		__ntapi,
dd89bb
		import_table,
dd89bb
		__NT_IMPORTED_SYMBOLS_ARRAY_SIZE);
dd89bb
dd89bb
	/* alternate implementation */
dd89bb
	__ntapi->rtl_init_unicode_string 			= __ntapi_tt_init_unicode_string_from_utf16;
47cc6e
	__ntapi->strlen						= __ntapi_tt_string_null_offset_multibyte;
47cc6e
	__ntapi->wcslen						= __ntapi_tt_wcslen;
dd89bb
dd89bb
	/* extension functions */
dd89bb
	/* nt_object.h */
dd89bb
	__ntapi->tt_create_keyed_object_directory		= __ntapi_tt_create_keyed_object_directory;
dd89bb
	__ntapi->tt_open_keyed_object_directory			= __ntapi_tt_open_keyed_object_directory;
dd89bb
	__ntapi->tt_create_keyed_object_directory_entry		= __ntapi_tt_create_keyed_object_directory_entry;
dd89bb
dd89bb
	/* nt_crc32.h */
dd89bb
	__ntapi->tt_buffer_crc32 				= __ntapi_tt_buffer_crc32;
dd89bb
	__ntapi->tt_mbstr_crc32					= __ntapi_tt_mbstr_crc32;
dd89bb
	__ntapi->tt_crc32_table					= __ntapi_tt_crc32_table;
dd89bb
dd89bb
	/* nt_file.h */
fc3ec7
	__ntapi->tt_get_file_handle_type			= __ntapi_tt_get_file_handle_type;
dd89bb
	__ntapi->tt_open_logical_parent_directory		= __ntapi_tt_open_logical_parent_directory;
dd89bb
	__ntapi->tt_open_physical_parent_directory		= __ntapi_tt_open_physical_parent_directory;
dd89bb
dd89bb
	/* nt_ldr.h */
dd89bb
	__ntapi->ldr_load_system_dll				= __ntapi_ldr_load_system_dll;
dd89bb
	__ntapi->ldr_create_state_snapshot			= __ntapi_ldr_create_state_snapshot;
dd89bb
	__ntapi->ldr_revert_state_to_snapshot			= __ntapi_ldr_revert_state_to_snapshot;
dd89bb
dd89bb
	/* nt_string.h */
dd89bb
	__ntapi->tt_string_null_offset_multibyte 		= __ntapi_tt_string_null_offset_multibyte;
dd89bb
	__ntapi->tt_string_null_offset_short			= __ntapi_tt_string_null_offset_short;
dd89bb
	__ntapi->tt_string_null_offset_dword			= __ntapi_tt_string_null_offset_dword;
dd89bb
	__ntapi->tt_string_null_offset_qword			= __ntapi_tt_string_null_offset_qword;
dd89bb
	__ntapi->tt_string_null_offset_ptrsize			= __ntapi_tt_string_null_offset_ptrsize;
c30ed7
	__ntapi->tt_strcmp_multibyte				= __ntapi_tt_strcmp_multibyte;
060ead
	__ntapi->tt_strcmp_utf16				= __ntapi_tt_strcmp_utf16;
964eed
	__ntapi->tt_strncmp_multibyte				= __ntapi_tt_strncmp_multibyte;
a2ea1b
	__ntapi->tt_strncmp_utf16				= __ntapi_tt_strncmp_utf16;
dd89bb
	__ntapi->tt_aligned_block_memset 			= __ntapi_tt_aligned_block_memset;
dd89bb
	__ntapi->tt_aligned_block_memcpy 			= __ntapi_tt_aligned_block_memcpy;
dd89bb
	__ntapi->tt_memcpy_utf16 				= __ntapi_tt_memcpy_utf16;
dd89bb
	__ntapi->tt_aligned_memcpy_utf16 			= __ntapi_tt_aligned_memcpy_utf16;
dd89bb
	__ntapi->tt_generic_memset				= __ntapi_tt_generic_memset;
dd89bb
	__ntapi->tt_generic_memcpy 				= __ntapi_tt_generic_memcpy;
dd89bb
	__ntapi->tt_uint16_to_hex_utf16				= __ntapi_tt_uint16_to_hex_utf16;
dd89bb
	__ntapi->tt_uint32_to_hex_utf16				= __ntapi_tt_uint32_to_hex_utf16;
dd89bb
	__ntapi->tt_uint64_to_hex_utf16				= __ntapi_tt_uint64_to_hex_utf16;
dd89bb
	__ntapi->tt_uintptr_to_hex_utf16 			= __ntapi_tt_uintptr_to_hex_utf16;
dd89bb
	__ntapi->tt_hex_utf16_to_uint16				= __ntapi_tt_hex_utf16_to_uint16;
dd89bb
	__ntapi->tt_hex_utf16_to_uint32				= __ntapi_tt_hex_utf16_to_uint32;
dd89bb
	__ntapi->tt_hex_utf16_to_uint64				= __ntapi_tt_hex_utf16_to_uint64;
dd89bb
	__ntapi->tt_hex_utf16_to_uintptr 			= __ntapi_tt_hex_utf16_to_uintptr;
dd89bb
	__ntapi->tt_init_unicode_string_from_utf16 		= __ntapi_tt_init_unicode_string_from_utf16;
dd89bb
	__ntapi->tt_uint16_to_hex_utf8				= __ntapi_tt_uint16_to_hex_utf8;
dd89bb
	__ntapi->tt_uint32_to_hex_utf8				= __ntapi_tt_uint32_to_hex_utf8;
dd89bb
	__ntapi->tt_uint64_to_hex_utf8				= __ntapi_tt_uint64_to_hex_utf8;
dd89bb
	__ntapi->tt_uintptr_to_hex_utf8				= __ntapi_tt_uintptr_to_hex_utf8;
dd89bb
dd89bb
	/* nt_guid.h */
dd89bb
	__ntapi->tt_guid_copy 					= __ntapi_tt_guid_copy;
dd89bb
	__ntapi->tt_guid_compare 				= __ntapi_tt_guid_compare;
dd89bb
	__ntapi->tt_guid_to_utf16_string 			= __ntapi_tt_guid_to_utf16_string;
dd89bb
	__ntapi->tt_utf16_string_to_guid 			= __ntapi_tt_utf16_string_to_guid;
dd89bb
dd89bb
	/* nt_sysinfo.h */
dd89bb
	__ntapi->tt_get_system_directory_native_path 		= __ntapi_tt_get_system_directory_native_path;
dd89bb
	__ntapi->tt_get_system_directory_dos_path 		= __ntapi_tt_get_system_directory_dos_path;
dd89bb
	__ntapi->tt_get_system_directory_handle			= __ntapi_tt_get_system_directory_handle;
dd89bb
	__ntapi->tt_get_system_info_snapshot  			= __ntapi_tt_get_system_info_snapshot;
dd89bb
dd89bb
	/* nt_thread.h */
dd89bb
	__ntapi->tt_create_local_thread				= __ntapi_tt_create_local_thread;
dd89bb
	__ntapi->tt_create_remote_thread 			= __ntapi_tt_create_remote_thread;
dd89bb
	__ntapi->tt_create_thread 				= __ntapi_tt_create_thread;
dd89bb
dd89bb
	/* nt_process.h */
dd89bb
	__ntapi->tt_create_remote_process_params 		= __ntapi_tt_create_remote_process_params;
c164ff
	__ntapi->tt_spawn_native_process			= __ntapi_tt_spawn_native_process;
dd89bb
	__ntapi->tt_get_runtime_data 				= __ntapi_tt_get_runtime_data;
dd89bb
	__ntapi->tt_init_runtime_data				= __ntapi_tt_init_runtime_data;
dd89bb
	__ntapi->tt_update_runtime_data				= __ntapi_tt_update_runtime_data;
dd89bb
	__ntapi->tt_exec_map_image_as_data			= __ntapi_tt_exec_map_image_as_data;
dd89bb
	__ntapi->tt_exec_unmap_image				= __ntapi_tt_exec_unmap_image;
dd89bb
5f1999
	/* nt_token.h */
5f1999
	__ntapi->tt_enable_token_privilege			= __ntapi_tt_enable_token_privilege;
5f1999
	__ntapi->tt_disable_token_privilege			= __ntapi_tt_disable_token_privilege;
5f1999
dd89bb
	/* nt_section.h */
dd89bb
	__ntapi->tt_get_section_name 				= __ntapi_tt_get_section_name;
dd89bb
dd89bb
	/* nt_sync.h */
dd89bb
	__ntapi->tt_create_inheritable_event 			= __ntapi_tt_create_inheritable_event;
dd89bb
	__ntapi->tt_create_private_event 			= __ntapi_tt_create_private_event;
dd89bb
	__ntapi->tt_wait_for_dummy_event 			= __ntapi_tt_wait_for_dummy_event;
dd89bb
	__ntapi->tt_sync_block_init 				= __ntapi_tt_sync_block_init;
dd89bb
	__ntapi->tt_sync_block_lock 				= __ntapi_tt_sync_block_lock;
dd89bb
	__ntapi->tt_sync_block_server_lock 			= __ntapi_tt_sync_block_server_lock;
dd89bb
	__ntapi->tt_sync_block_unlock 				= __ntapi_tt_sync_block_unlock;
dd89bb
	__ntapi->tt_sync_block_invalidate 			= __ntapi_tt_sync_block_invalidate;
dd89bb
dd89bb
	/* nt_port.h */
dd89bb
	__ntapi->csr_port_handle 				= __ntapi_csr_port_handle;
dd89bb
	__ntapi->tt_port_guid_from_type				= __ntapi_tt_port_guid_from_type;
dd89bb
	__ntapi->tt_port_type_from_guid				= __ntapi_tt_port_type_from_guid;
dd89bb
	__ntapi->tt_port_generate_keys 				= __ntapi_tt_port_generate_keys;
dd89bb
	__ntapi->tt_port_format_keys 				= __ntapi_tt_port_format_keys;
dd89bb
	__ntapi->tt_port_name_from_attributes 			= __ntapi_tt_port_name_from_attributes;
dd89bb
dd89bb
	/* nt_argv.h */
dd89bb
	__ntapi->tt_get_cmd_line_utf16 				= __ntapi_tt_get_cmd_line_utf16;
dd89bb
	__ntapi->tt_get_peb_env_block_utf16 			= __ntapi_tt_get_peb_env_block_utf16;
dd89bb
	__ntapi->tt_parse_cmd_line_args_utf16 			= __ntapi_tt_parse_cmd_line_args_utf16;
dd89bb
	__ntapi->tt_get_argv_envp_utf8 				= __ntapi_tt_get_argv_envp_utf8;
dd89bb
	__ntapi->tt_get_argv_envp_utf16				= __ntapi_tt_get_argv_envp_utf16;
dd89bb
	__ntapi->tt_get_env_var_meta_utf16 			= __ntapi_tt_get_env_var_meta_utf16;
dd89bb
	__ntapi->tt_array_copy_utf16				= __ntapi_tt_array_copy_utf16;
dd89bb
	__ntapi->tt_array_copy_utf8				= __ntapi_tt_array_copy_utf8;
dd89bb
	__ntapi->tt_array_convert_utf8_to_utf16			= __ntapi_tt_array_convert_utf8_to_utf16;
dd89bb
	__ntapi->tt_array_convert_utf16_to_utf8			= __ntapi_tt_array_convert_utf16_to_utf8;
dd89bb
dd89bb
	/* nt_blitter.h */
dd89bb
	__ntapi->blt_alloc					= __ntapi_blt_alloc;
dd89bb
	__ntapi->blt_free					= __ntapi_blt_free;
dd89bb
	__ntapi->blt_acquire					= __ntapi_blt_acquire;
dd89bb
	__ntapi->blt_obtain					= __ntapi_blt_obtain;
dd89bb
	__ntapi->blt_possess					= __ntapi_blt_possess;
dd89bb
	__ntapi->blt_release					= __ntapi_blt_release;
dd89bb
	__ntapi->blt_get 					= __ntapi_blt_get;
dd89bb
	__ntapi->blt_set 					= __ntapi_blt_set;
dd89bb
dd89bb
	/* nt_unicode.h */
dd89bb
	__ntapi->uc_validate_unicode_stream_utf8 		= __ntapi_uc_validate_unicode_stream_utf8;
dd89bb
	__ntapi->uc_validate_unicode_stream_utf16 		= __ntapi_uc_validate_unicode_stream_utf16;
dd89bb
	__ntapi->uc_get_code_point_byte_count_utf8		= __ntapi_uc_get_code_point_byte_count_utf8;
dd89bb
	__ntapi->uc_get_code_point_byte_count_utf16		= __ntapi_uc_get_code_point_byte_count_utf16;
dd89bb
	__ntapi->uc_convert_unicode_stream_utf8_to_utf16 	= __ntapi_uc_convert_unicode_stream_utf8_to_utf16;
dd89bb
	__ntapi->uc_convert_unicode_stream_utf8_to_utf32 	= __ntapi_uc_convert_unicode_stream_utf8_to_utf32;
dd89bb
	__ntapi->uc_convert_unicode_stream_utf16_to_utf8 	= __ntapi_uc_convert_unicode_stream_utf16_to_utf8;
dd89bb
	__ntapi->uc_convert_unicode_stream_utf16_to_utf32 	= __ntapi_uc_convert_unicode_stream_utf16_to_utf32;
dd89bb
dd89bb
	/* nt_daemon.h */
dd89bb
	__ntapi->dsr_init					= __ntapi_dsr_init;
dd89bb
	__ntapi->dsr_start					= __ntapi_dsr_start;
dd89bb
	__ntapi->dsr_create_port 				= __ntapi_dsr_create_port;
dd89bb
	__ntapi->dsr_connect_internal_client			= __ntapi_dsr_connect_internal_client;
dd89bb
	__ntapi->dsr_internal_client_connect			= __ntapi_dsr_internal_client_connect;
dd89bb
dd89bb
	/* nt_vfd.h */
dd89bb
	__ntapi->vfd_dev_name_init				= __ntapi_vfd_dev_name_init;
dd89bb
dd89bb
	/* nt_tty.h */
dd89bb
	__ntapi->tty_create_session				= __ntapi_tty_create_session;
dd89bb
	__ntapi->tty_join_session				= __ntapi_tty_join_session;
dd89bb
	__ntapi->tty_connect					= __ntapi_tty_connect;
dd89bb
	__ntapi->tty_client_session_query			= __ntapi_tty_client_session_query;
dd89bb
	__ntapi->tty_client_session_set				= __ntapi_tty_client_session_set;
dd89bb
	__ntapi->tty_client_process_register			= __ntapi_tty_client_process_register;
dd89bb
	__ntapi->tty_query_information_server			= __ntapi_tty_query_information_server;
dd89bb
	__ntapi->tty_request_peer				= __ntapi_tty_request_peer;
dd89bb
	__ntapi->tty_vms_query					= __ntapi_tty_vms_query;
dd89bb
	__ntapi->tty_vms_request 				= __ntapi_tty_vms_request;
dd89bb
	__ntapi->pty_open					= __ntapi_pty_open;
dd89bb
	__ntapi->pty_reopen					= __ntapi_pty_reopen;
efc01e
	__ntapi->pty_inherit 					= __ntapi_pty_inherit;
dd89bb
	__ntapi->pty_close					= __ntapi_pty_close;
dd89bb
	__ntapi->pty_read					= __ntapi_pty_read;
dd89bb
	__ntapi->pty_write					= __ntapi_pty_write;
dd89bb
	__ntapi->pty_ioctl					= __ntapi_pty_ioctl;
dd89bb
	__ntapi->pty_query					= __ntapi_pty_query;
fc3ec7
	__ntapi->pty_set					= __ntapi_pty_set;
dd89bb
	__ntapi->pty_cancel					= __ntapi_pty_cancel;
dd89bb
dd89bb
	/* nt_socket.h */
dd89bb
	__ntapi->sc_listen					= __ntapi_sc_listen;
dd89bb
	__ntapi->sc_accept					= __ntapi_sc_accept;
dd89bb
	__ntapi->sc_send 					= __ntapi_sc_send;
dd89bb
	__ntapi->sc_recv 					= __ntapi_sc_recv;
dd89bb
	__ntapi->sc_shutdown					= __ntapi_sc_shutdown;
dd89bb
	__ntapi->sc_server_duplicate_socket			= __ntapi_sc_server_duplicate_socket;
830346
	__ntapi->sc_setsockopt					= __ntapi_sc_setsockopt;
419228
	__ntapi->sc_getsockopt					= __ntapi_sc_getsockopt;
dd89bb
	__ntapi->sc_wait = __ntapi_sc_wait;
dd89bb
dd89bb
	/* nt_mount.h */
dd89bb
	__ntapi->tt_get_dos_drive_device_handle			= __ntapi_tt_get_dos_drive_device_handle;
dd89bb
	__ntapi->tt_get_dos_drive_root_handle			= __ntapi_tt_get_dos_drive_root_handle;
dd89bb
	__ntapi->tt_get_dos_drive_device_name			= __ntapi_tt_get_dos_drive_device_name;
dd89bb
	__ntapi->tt_get_dos_drive_mount_points			= __ntapi_tt_get_dos_drive_mount_points;
dd89bb
	__ntapi->tt_dev_mount_points_to_statfs			= __ntapi_tt_dev_mount_points_to_statfs;
dd89bb
	__ntapi->tt_get_dos_drive_letter_from_device		= __ntapi_tt_get_dos_drive_letter_from_device;
dd89bb
dd89bb
	/* nt_istat.h */
dd89bb
	__ntapi->tt_istat					= __ntapi_tt_istat;
dd89bb
	__ntapi->tt_validate_fs_handle				= __ntapi_tt_validate_fs_handle;
dd89bb
dd89bb
	/* nt_stat.h */
dd89bb
	__ntapi->tt_stat 					= __ntapi_tt_stat;
dd89bb
dd89bb
	/* nt_statfs.h */
dd89bb
	__ntapi->tt_statfs					= __ntapi_tt_statfs;
dd89bb
dd89bb
	/* nt_vmount.h */
dd89bb
	__ntapi->vms_get_node_by_dev_name			= __ntapi_vms_get_node_by_dev_name;
dd89bb
	__ntapi->vms_get_node_by_end_component			= __ntapi_vms_get_node_by_end_component;
dd89bb
	__ntapi->vms_cache_alloc 				= __ntapi_vms_cache_alloc;
dd89bb
	__ntapi->vms_cache_free					= __ntapi_vms_cache_free;
dd89bb
	__ntapi->vms_client_connect				= __ntapi_vms_client_connect;
dd89bb
	__ntapi->vms_client_disconnect				= __ntapi_vms_client_disconnect;
dd89bb
	__ntapi->vms_point_attach				= __ntapi_vms_point_attach;
dd89bb
	__ntapi->vms_point_get_handles				= __ntapi_vms_point_get_handles;
dd89bb
	__ntapi->vms_ref_count_inc				= __ntapi_vms_ref_count_inc;
dd89bb
	__ntapi->vms_ref_count_dec				= __ntapi_vms_ref_count_dec;
dd89bb
	__ntapi->vms_table_query 				= __ntapi_vms_table_query;
dd89bb
dd89bb
	/* nt_debug.h */
dd89bb
	#ifdef __DEBUG
dd89bb
	__ntapi->dbg_write					= __dbg_write;
dd89bb
	__ntapi->dbg_fn_call					= __dbg_fn_call;
dd89bb
	__ntapi->dbg_msg 					= __dbg_msg;
dd89bb
	#endif
dd89bb
dd89bb
dd89bb
	/* OS version dependent functions */
dd89bb
	if (__ntapi->zw_create_user_process) {
dd89bb
		__ntapi->tt_fork 				= __ntapi_tt_fork_v2;
dd89bb
		__ntapi->tt_create_native_process		= __ntapi_tt_create_native_process_v2;
dd89bb
		__ntapi->ipc_create_pipe 			= __ntapi_ipc_create_pipe_v2;
dd89bb
		__ntapi->sc_socket				= __ntapi_sc_socket_v2;
dd89bb
		__ntapi->sc_bind 				= __ntapi_sc_bind_v2;
dd89bb
		__ntapi->sc_connect				= __ntapi_sc_connect_v2;
dd89bb
		__ntapi->sc_server_accept_connection		= __ntapi_sc_server_accept_connection_v2;
dd89bb
		__ntapi->sc_getsockname				= __ntapi_sc_getsockname_v2;
5d8625
		__ntapi->sc_getpeername				= __ntapi_sc_getpeername_v2;
dd89bb
	} else {
dd89bb
		__ntapi->tt_fork = __ntapi_tt_fork_v1;
dd89bb
		__ntapi->tt_create_native_process		= __ntapi_tt_create_native_process_v1;
dd89bb
		__ntapi->ipc_create_pipe 			= __ntapi_ipc_create_pipe_v1;
dd89bb
		__ntapi->sc_socket				= __ntapi_sc_socket_v1;
dd89bb
		__ntapi->sc_bind 				= __ntapi_sc_bind_v1;
dd89bb
		__ntapi->sc_connect				= __ntapi_sc_connect_v1;
dd89bb
		__ntapi->sc_server_accept_connection		= __ntapi_sc_server_accept_connection_v1;
dd89bb
		__ntapi->sc_getsockname				= __ntapi_sc_getsockname_v1;
5d8625
		__ntapi->sc_getpeername				= __ntapi_sc_getpeername_v1;
dd89bb
	}
dd89bb
dd89bb
	/* internals */
dd89bb
	internals->ntapi_img_sec_bss				= &__ntapi_img_bss;
dd89bb
	internals->subsystem					= &__ntapi_rdata.img_sec_data.__session_name;
dd89bb
dd89bb
	internals->tt_get_csr_port_handle_addr_by_logic		= __GET_CSR_PORT_HANDLE_BY_LOGIC;
dd89bb
	internals->csr_port_handle_addr				= __GET_CSR_PORT_HANDLE_BY_LOGIC();
dd89bb
dd89bb
	/* shadow copy for client libraries */
dd89bb
	__ntapi->tt_aligned_block_memcpy(
dd89bb
		(uintptr_t *)&___ntapi_shadow,
dd89bb
		(uintptr_t *)&___ntapi,
dd89bb
		sizeof(ntapi_vtbl));
dd89bb
a3e9aa
	/* process token */
a3e9aa
	 if ((status = __ntapi->zw_open_process_token(
a3e9aa
			NT_CURRENT_PROCESS_HANDLE,
a3e9aa
			NT_TOKEN_ALL_ACCESS,
a3e9aa
			&internals->htoken)))
a3e9aa
		return status;
a3e9aa
dd89bb
	/* done */
dd89bb
	*pvtbl	= &___ntapi_shadow;
dd89bb
	at_locked_inc(&__ntapi_init_idx);
dd89bb
dd89bb
	return NT_STATUS_SUCCESS;
dd89bb
}
dd89bb
dd89bb
dd89bb
static int32_t __fastcall __ntapi_init_pending(ntapi_vtbl ** pvtbl)
dd89bb
{
c713d8
	(void)pvtbl;
dd89bb
	return NT_STATUS_PENDING;
dd89bb
}
dd89bb
dd89bb
static int32_t __fastcall __ntapi_init_completed(ntapi_vtbl ** pvtbl)
dd89bb
{
208f43
	*pvtbl = &___ntapi_shadow;
dd89bb
	return NT_STATUS_SUCCESS;
dd89bb
};
dd89bb
dd89bb
dd89bb
__ntapi_api
dd89bb
int32_t __fastcall ntapi_init(ntapi_vtbl ** pvtbl)
dd89bb
{
dd89bb
	return __ntapi_init_vtbl[__ntapi_init_idx](pvtbl);
dd89bb
}
dd89bb
dd89bb
dd89bb
ntapi_internals * __cdecl __ntapi_internals(void)
dd89bb
{
dd89bb
	return internals;
dd89bb
}