summaryrefslogtreecommitdiffhomepage
path: root/src/internal/ntapi.c
diff options
context:
space:
mode:
authormidipix <writeonce@midipix.org>2015-07-27 04:01:18 -0400
committermidipix <writeonce@midipix.org>2015-07-27 04:01:18 -0400
commitdd89bb8ad4fe184a34b5dbdda237e640fc82121b (patch)
tree5e80d2da35f5892f92be29f57982b2708e6bd99b /src/internal/ntapi.c
parentdcdadc2702712fa750ed255ed1dfa354522797a0 (diff)
downloadntapi-dd89bb8ad4fe184a34b5dbdda237e640fc82121b.tar.bz2
ntapi-dd89bb8ad4fe184a34b5dbdda237e640fc82121b.tar.xz
entered advanced internal development stage.
Diffstat (limited to 'src/internal/ntapi.c')
-rw-r--r--src/internal/ntapi.c411
1 files changed, 411 insertions, 0 deletions
diff --git a/src/internal/ntapi.c b/src/internal/ntapi.c
new file mode 100644
index 0000000..2340c47
--- /dev/null
+++ b/src/internal/ntapi.c
@@ -0,0 +1,411 @@
+/********************************************************/
+/* ntapi: Native API core library */
+/* Copyright (C) 2013,2014,2015 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_crc32.h>
+#include <ntapi/nt_object.h>
+#include <ntapi/nt_sysinfo.h>
+#include <ntapi/nt_memory.h>
+#include <ntapi/nt_section.h>
+#include <ntapi/nt_thread.h>
+#include <ntapi/nt_process.h>
+#include <ntapi/nt_job.h>
+#include <ntapi/nt_token.h>
+#include <ntapi/nt_sync.h>
+#include <ntapi/nt_time.h>
+#include <ntapi/nt_profiling.h>
+#include <ntapi/nt_port.h>
+#include <ntapi/nt_device.h>
+#include <ntapi/nt_file.h>
+#include <ntapi/nt_registry.h>
+#include <ntapi/nt_security.h>
+#include <ntapi/nt_pnp.h>
+#include <ntapi/nt_exception.h>
+#include <ntapi/nt_locale.h>
+#include <ntapi/nt_uuid.h>
+#include <ntapi/nt_atom.h>
+#include <ntapi/nt_os.h>
+#include <ntapi/nt_ldr.h>
+#include <ntapi/nt_string.h>
+#include <ntapi/nt_guid.h>
+#include <ntapi/nt_argv.h>
+#include <ntapi/nt_blitter.h>
+#include <ntapi/nt_unicode.h>
+#include <ntapi/nt_socket.h>
+#include <ntapi/nt_mount.h>
+#include <ntapi/nt_istat.h>
+#include <ntapi/nt_stat.h>
+#include <ntapi/nt_statfs.h>
+#include <ntapi/nt_daemon.h>
+#include <ntapi/nt_tty.h>
+#include <ntapi/nt_vmount.h>
+#include <ntapi/nt_hash.h>
+#include <ntapi/nt_debug.h>
+#include <ntapi/nt_atomic.h>
+#include <ntapi/ntapi.h>
+
+#include "ntapi_impl.h"
+#include "ntapi_hash_table.h"
+
+/* simplified once mechanism for free-standing applications */
+typedef int32_t __fastcall __ntapi_init_fn(ntapi_vtbl ** pvtbl);
+
+static __ntapi_init_fn __ntapi_init_once;
+static __ntapi_init_fn __ntapi_init_pending;
+static __ntapi_init_fn __ntapi_init_completed;
+
+static intptr_t __ntapi_init_idx = 0;
+static __ntapi_init_fn * __ntapi_init_vtbl[3] = {
+ __ntapi_init_once,
+ __ntapi_init_pending,
+ __ntapi_init_completed};
+
+/* accessor */
+ntapi_vtbl ___ntapi = {0};
+ntapi_vtbl ___ntapi_shadow = {0};
+
+/* .bss */
+static __ntapi_img_sec_bss __ntapi_img_bss;
+
+/* .rdata */
+static union __ntapi_img_rdata __ntapi_rdata = {{
+ {__NTAPI_HASH_TABLE}, /* __ntapi_import_table */
+ 0, /* __ntapi */
+ {{0}}, /* __session_name */
+ 0}}; /* __internals */
+
+#define internals __ntapi_rdata.img_sec_data.__internals
+#define import_table __ntapi_rdata.img_sec_data.__ntapi_import_table
+
+
+static int32_t __fastcall __ntapi_init_once(ntapi_vtbl ** pvtbl)
+{
+ int32_t status;
+ void * hntdll;
+ size_t block_size;
+ ntapi_zw_allocate_virtual_memory * pfn_zw_allocate_virtual_memory;
+ char fname_allocate_virtual_memory[] =
+ "ZwAllocateVirtualMemory";
+ /* once */
+ at_locked_inc(&__ntapi_init_idx);
+
+ /* pvtbl */
+ if (!(pvtbl))
+ return NT_STATUS_INVALID_PARAMETER;
+ else
+ *pvtbl = (ntapi_vtbl *)0;
+
+ /* ntdll */
+ if (!(hntdll = pe_get_ntdll_module_handle()))
+ return NT_STATUS_DLL_INIT_FAILED;
+
+ pfn_zw_allocate_virtual_memory = (ntapi_zw_allocate_virtual_memory *)
+ pe_get_procedure_address(
+ hntdll,
+ fname_allocate_virtual_memory);
+
+ if (!pfn_zw_allocate_virtual_memory)
+ return NT_STATUS_DLL_INIT_FAILED;
+
+ /* ntapi_internals: alloc */
+ block_size = sizeof(ntapi_internals);
+ status = pfn_zw_allocate_virtual_memory(
+ NT_CURRENT_PROCESS_HANDLE,
+ (void **)&internals,
+ 0,
+ &block_size,
+ NT_MEM_COMMIT,
+ NT_PAGE_READWRITE);
+
+ if (status != NT_STATUS_SUCCESS)
+ return status;
+
+ /* hashed import table */
+ __ntapi_tt_populate_hashed_import_table(
+ pe_get_ntdll_module_handle(),
+ __ntapi,
+ import_table,
+ __NT_IMPORTED_SYMBOLS_ARRAY_SIZE);
+
+ /* alternate implementation */
+ __ntapi->rtl_init_unicode_string = __ntapi_tt_init_unicode_string_from_utf16;
+
+ /* extension functions */
+ /* nt_object.h */
+ __ntapi->tt_create_keyed_object_directory = __ntapi_tt_create_keyed_object_directory;
+ __ntapi->tt_open_keyed_object_directory = __ntapi_tt_open_keyed_object_directory;
+ __ntapi->tt_create_keyed_object_directory_entry = __ntapi_tt_create_keyed_object_directory_entry;
+
+ /* nt_crc32.h */
+ __ntapi->tt_buffer_crc32 = __ntapi_tt_buffer_crc32;
+ __ntapi->tt_mbstr_crc32 = __ntapi_tt_mbstr_crc32;
+ __ntapi->tt_crc32_table = __ntapi_tt_crc32_table;
+
+ /* nt_file.h */
+ __ntapi->tt_get_file_handle_type = __ntapi_tt_get_file_handle_type;
+ __ntapi->tt_open_logical_parent_directory = __ntapi_tt_open_logical_parent_directory;
+ __ntapi->tt_open_physical_parent_directory = __ntapi_tt_open_physical_parent_directory;
+
+ /* nt_ldr.h */
+ __ntapi->ldr_load_system_dll = __ntapi_ldr_load_system_dll;
+ __ntapi->ldr_create_state_snapshot = __ntapi_ldr_create_state_snapshot;
+ __ntapi->ldr_revert_state_to_snapshot = __ntapi_ldr_revert_state_to_snapshot;
+
+ /* nt_string.h */
+ __ntapi->tt_string_null_offset_multibyte = __ntapi_tt_string_null_offset_multibyte;
+ __ntapi->tt_string_null_offset_short = __ntapi_tt_string_null_offset_short;
+ __ntapi->tt_string_null_offset_dword = __ntapi_tt_string_null_offset_dword;
+ __ntapi->tt_string_null_offset_qword = __ntapi_tt_string_null_offset_qword;
+ __ntapi->tt_string_null_offset_ptrsize = __ntapi_tt_string_null_offset_ptrsize;
+ __ntapi->strlen = __ntapi_tt_string_null_offset_multibyte;
+ __ntapi->wcslen = __ntapi_wcslen;
+ __ntapi->tt_aligned_block_memset = __ntapi_tt_aligned_block_memset;
+ __ntapi->tt_aligned_block_memcpy = __ntapi_tt_aligned_block_memcpy;
+ __ntapi->tt_memcpy_utf16 = __ntapi_tt_memcpy_utf16;
+ __ntapi->tt_aligned_memcpy_utf16 = __ntapi_tt_aligned_memcpy_utf16;
+ __ntapi->tt_generic_memset = __ntapi_tt_generic_memset;
+ __ntapi->tt_generic_memcpy = __ntapi_tt_generic_memcpy;
+ __ntapi->tt_uint16_to_hex_utf16 = __ntapi_tt_uint16_to_hex_utf16;
+ __ntapi->tt_uint32_to_hex_utf16 = __ntapi_tt_uint32_to_hex_utf16;
+ __ntapi->tt_uint64_to_hex_utf16 = __ntapi_tt_uint64_to_hex_utf16;
+ __ntapi->tt_uintptr_to_hex_utf16 = __ntapi_tt_uintptr_to_hex_utf16;
+ __ntapi->tt_hex_utf16_to_uint16 = __ntapi_tt_hex_utf16_to_uint16;
+ __ntapi->tt_hex_utf16_to_uint32 = __ntapi_tt_hex_utf16_to_uint32;
+ __ntapi->tt_hex_utf16_to_uint64 = __ntapi_tt_hex_utf16_to_uint64;
+ __ntapi->tt_hex_utf16_to_uintptr = __ntapi_tt_hex_utf16_to_uintptr;
+ __ntapi->tt_init_unicode_string_from_utf16 = __ntapi_tt_init_unicode_string_from_utf16;
+ __ntapi->tt_uint16_to_hex_utf8 = __ntapi_tt_uint16_to_hex_utf8;
+ __ntapi->tt_uint32_to_hex_utf8 = __ntapi_tt_uint32_to_hex_utf8;
+ __ntapi->tt_uint64_to_hex_utf8 = __ntapi_tt_uint64_to_hex_utf8;
+ __ntapi->tt_uintptr_to_hex_utf8 = __ntapi_tt_uintptr_to_hex_utf8;
+
+ /* nt_guid.h */
+ __ntapi->tt_guid_copy = __ntapi_tt_guid_copy;
+ __ntapi->tt_guid_compare = __ntapi_tt_guid_compare;
+ __ntapi->tt_guid_to_utf16_string = __ntapi_tt_guid_to_utf16_string;
+ __ntapi->tt_utf16_string_to_guid = __ntapi_tt_utf16_string_to_guid;
+
+ /* nt_sysinfo.h */
+ __ntapi->tt_get_system_directory_native_path = __ntapi_tt_get_system_directory_native_path;
+ __ntapi->tt_get_system_directory_dos_path = __ntapi_tt_get_system_directory_dos_path;
+ __ntapi->tt_get_system_directory_handle = __ntapi_tt_get_system_directory_handle;
+ __ntapi->tt_get_system_info_snapshot = __ntapi_tt_get_system_info_snapshot;
+
+ /* nt_thread.h */
+ __ntapi->tt_create_local_thread = __ntapi_tt_create_local_thread;
+ __ntapi->tt_create_remote_thread = __ntapi_tt_create_remote_thread;
+ __ntapi->tt_create_thread = __ntapi_tt_create_thread;
+
+ /* nt_process.h */
+ __ntapi->tt_create_remote_process_params = __ntapi_tt_create_remote_process_params;
+ __ntapi->tt_get_runtime_data = __ntapi_tt_get_runtime_data;
+ __ntapi->tt_init_runtime_data = __ntapi_tt_init_runtime_data;
+ __ntapi->tt_update_runtime_data = __ntapi_tt_update_runtime_data;
+ __ntapi->tt_exec_map_image_as_data = __ntapi_tt_exec_map_image_as_data;
+ __ntapi->tt_exec_unmap_image = __ntapi_tt_exec_unmap_image;
+
+ /* nt_section.h */
+ __ntapi->tt_get_section_name = __ntapi_tt_get_section_name;
+
+ /* nt_sync.h */
+ __ntapi->tt_create_inheritable_event = __ntapi_tt_create_inheritable_event;
+ __ntapi->tt_create_private_event = __ntapi_tt_create_private_event;
+ __ntapi->tt_wait_for_dummy_event = __ntapi_tt_wait_for_dummy_event;
+ __ntapi->tt_sync_block_init = __ntapi_tt_sync_block_init;
+ __ntapi->tt_sync_block_lock = __ntapi_tt_sync_block_lock;
+ __ntapi->tt_sync_block_server_lock = __ntapi_tt_sync_block_server_lock;
+ __ntapi->tt_sync_block_unlock = __ntapi_tt_sync_block_unlock;
+ __ntapi->tt_sync_block_invalidate = __ntapi_tt_sync_block_invalidate;
+
+ /* nt_port.h */
+ __ntapi->csr_port_handle = __ntapi_csr_port_handle;
+ __ntapi->tt_port_guid_from_type = __ntapi_tt_port_guid_from_type;
+ __ntapi->tt_port_type_from_guid = __ntapi_tt_port_type_from_guid;
+ __ntapi->tt_port_generate_keys = __ntapi_tt_port_generate_keys;
+ __ntapi->tt_port_format_keys = __ntapi_tt_port_format_keys;
+ __ntapi->tt_port_name_from_attributes = __ntapi_tt_port_name_from_attributes;
+
+ /* nt_argv.h */
+ __ntapi->tt_get_cmd_line_utf16 = __ntapi_tt_get_cmd_line_utf16;
+ __ntapi->tt_get_peb_env_block_utf16 = __ntapi_tt_get_peb_env_block_utf16;
+ __ntapi->tt_parse_cmd_line_args_utf16 = __ntapi_tt_parse_cmd_line_args_utf16;
+ __ntapi->tt_get_argv_envp_utf8 = __ntapi_tt_get_argv_envp_utf8;
+ __ntapi->tt_get_argv_envp_utf16 = __ntapi_tt_get_argv_envp_utf16;
+ __ntapi->tt_get_env_var_meta_utf16 = __ntapi_tt_get_env_var_meta_utf16;
+ __ntapi->tt_get_short_option_meta_utf16 = __ntapi_tt_get_short_option_meta_utf16;
+ __ntapi->tt_get_long_option_meta_utf16 = __ntapi_tt_get_long_option_meta_utf16;
+ __ntapi->tt_array_copy_utf16 = __ntapi_tt_array_copy_utf16;
+ __ntapi->tt_array_copy_utf8 = __ntapi_tt_array_copy_utf8;
+ __ntapi->tt_array_convert_utf8_to_utf16 = __ntapi_tt_array_convert_utf8_to_utf16;
+ __ntapi->tt_array_convert_utf16_to_utf8 = __ntapi_tt_array_convert_utf16_to_utf8;
+
+ /* nt_blitter.h */
+ __ntapi->blt_alloc = __ntapi_blt_alloc;
+ __ntapi->blt_free = __ntapi_blt_free;
+ __ntapi->blt_acquire = __ntapi_blt_acquire;
+ __ntapi->blt_obtain = __ntapi_blt_obtain;
+ __ntapi->blt_possess = __ntapi_blt_possess;
+ __ntapi->blt_release = __ntapi_blt_release;
+ __ntapi->blt_get = __ntapi_blt_get;
+ __ntapi->blt_set = __ntapi_blt_set;
+
+ /* nt_unicode.h */
+ __ntapi->uc_validate_unicode_stream_utf8 = __ntapi_uc_validate_unicode_stream_utf8;
+ __ntapi->uc_validate_unicode_stream_utf16 = __ntapi_uc_validate_unicode_stream_utf16;
+ __ntapi->uc_get_code_point_byte_count_utf8 = __ntapi_uc_get_code_point_byte_count_utf8;
+ __ntapi->uc_get_code_point_byte_count_utf16 = __ntapi_uc_get_code_point_byte_count_utf16;
+ __ntapi->uc_convert_unicode_stream_utf8_to_utf16 = __ntapi_uc_convert_unicode_stream_utf8_to_utf16;
+ __ntapi->uc_convert_unicode_stream_utf8_to_utf32 = __ntapi_uc_convert_unicode_stream_utf8_to_utf32;
+ __ntapi->uc_convert_unicode_stream_utf16_to_utf8 = __ntapi_uc_convert_unicode_stream_utf16_to_utf8;
+ __ntapi->uc_convert_unicode_stream_utf16_to_utf32 = __ntapi_uc_convert_unicode_stream_utf16_to_utf32;
+
+ /* nt_daemon.h */
+ __ntapi->dsr_init = __ntapi_dsr_init;
+ __ntapi->dsr_start = __ntapi_dsr_start;
+ __ntapi->dsr_create_port = __ntapi_dsr_create_port;
+ __ntapi->dsr_connect_internal_client = __ntapi_dsr_connect_internal_client;
+ __ntapi->dsr_internal_client_connect = __ntapi_dsr_internal_client_connect;
+
+ /* nt_vfd.h */
+ __ntapi->vfd_dev_name_init = __ntapi_vfd_dev_name_init;
+
+ /* nt_tty.h */
+ __ntapi->tty_create_session = __ntapi_tty_create_session;
+ __ntapi->tty_join_session = __ntapi_tty_join_session;
+ __ntapi->tty_connect = __ntapi_tty_connect;
+ __ntapi->tty_client_session_query = __ntapi_tty_client_session_query;
+ __ntapi->tty_client_session_set = __ntapi_tty_client_session_set;
+ __ntapi->tty_client_process_register = __ntapi_tty_client_process_register;
+ __ntapi->tty_query_information_server = __ntapi_tty_query_information_server;
+ __ntapi->tty_request_peer = __ntapi_tty_request_peer;
+ __ntapi->tty_vms_query = __ntapi_tty_vms_query;
+ __ntapi->tty_vms_request = __ntapi_tty_vms_request;
+ __ntapi->pty_open = __ntapi_pty_open;
+ __ntapi->pty_reopen = __ntapi_pty_reopen;
+ __ntapi->pty_close = __ntapi_pty_close;
+ __ntapi->pty_read = __ntapi_pty_read;
+ __ntapi->pty_write = __ntapi_pty_write;
+ __ntapi->pty_ioctl = __ntapi_pty_ioctl;
+ __ntapi->pty_query = __ntapi_pty_query;
+ __ntapi->pty_set = __ntapi_pty_set;
+ __ntapi->pty_cancel = __ntapi_pty_cancel;
+
+ /* nt_socket.h */
+ __ntapi->sc_listen = __ntapi_sc_listen;
+ __ntapi->sc_accept = __ntapi_sc_accept;
+ __ntapi->sc_send = __ntapi_sc_send;
+ __ntapi->sc_recv = __ntapi_sc_recv;
+ __ntapi->sc_shutdown = __ntapi_sc_shutdown;
+ __ntapi->sc_server_duplicate_socket = __ntapi_sc_server_duplicate_socket;
+ __ntapi->sc_wait = __ntapi_sc_wait;
+
+ /* nt_mount.h */
+ __ntapi->tt_get_dos_drive_device_handle = __ntapi_tt_get_dos_drive_device_handle;
+ __ntapi->tt_get_dos_drive_root_handle = __ntapi_tt_get_dos_drive_root_handle;
+ __ntapi->tt_get_dos_drive_device_name = __ntapi_tt_get_dos_drive_device_name;
+ __ntapi->tt_get_dos_drive_mount_points = __ntapi_tt_get_dos_drive_mount_points;
+ __ntapi->tt_dev_mount_points_to_statfs = __ntapi_tt_dev_mount_points_to_statfs;
+ __ntapi->tt_get_dos_drive_letter_from_device = __ntapi_tt_get_dos_drive_letter_from_device;
+
+ /* nt_istat.h */
+ __ntapi->tt_istat = __ntapi_tt_istat;
+ __ntapi->tt_validate_fs_handle = __ntapi_tt_validate_fs_handle;
+
+ /* nt_stat.h */
+ __ntapi->tt_stat = __ntapi_tt_stat;
+
+ /* nt_statfs.h */
+ __ntapi->tt_statfs = __ntapi_tt_statfs;
+
+ /* nt_vmount.h */
+ __ntapi->vms_get_node_by_dev_name = __ntapi_vms_get_node_by_dev_name;
+ __ntapi->vms_get_node_by_end_component = __ntapi_vms_get_node_by_end_component;
+ __ntapi->vms_cache_alloc = __ntapi_vms_cache_alloc;
+ __ntapi->vms_cache_free = __ntapi_vms_cache_free;
+ __ntapi->vms_client_connect = __ntapi_vms_client_connect;
+ __ntapi->vms_client_disconnect = __ntapi_vms_client_disconnect;
+ __ntapi->vms_point_attach = __ntapi_vms_point_attach;
+ __ntapi->vms_point_get_handles = __ntapi_vms_point_get_handles;
+ __ntapi->vms_ref_count_inc = __ntapi_vms_ref_count_inc;
+ __ntapi->vms_ref_count_dec = __ntapi_vms_ref_count_dec;
+ __ntapi->vms_table_query = __ntapi_vms_table_query;
+
+ /* nt_debug.h */
+ #ifdef __DEBUG
+ __ntapi->dbg_write = __dbg_write;
+ __ntapi->dbg_fn_call = __dbg_fn_call;
+ __ntapi->dbg_msg = __dbg_msg;
+ #endif
+
+
+ /* OS version dependent functions */
+ if (__ntapi->zw_create_user_process) {
+ __ntapi->tt_fork = __ntapi_tt_fork_v2;
+ __ntapi->tt_create_native_process = __ntapi_tt_create_native_process_v2;
+ __ntapi->ipc_create_pipe = __ntapi_ipc_create_pipe_v2;
+ __ntapi->sc_socket = __ntapi_sc_socket_v2;
+ __ntapi->sc_bind = __ntapi_sc_bind_v2;
+ __ntapi->sc_connect = __ntapi_sc_connect_v2;
+ __ntapi->sc_server_accept_connection = __ntapi_sc_server_accept_connection_v2;
+ __ntapi->sc_getsockname = __ntapi_sc_getsockname_v2;
+ } else {
+ __ntapi->tt_fork = __ntapi_tt_fork_v1;
+ __ntapi->tt_create_native_process = __ntapi_tt_create_native_process_v1;
+ __ntapi->ipc_create_pipe = __ntapi_ipc_create_pipe_v1;
+ __ntapi->sc_socket = __ntapi_sc_socket_v1;
+ __ntapi->sc_bind = __ntapi_sc_bind_v1;
+ __ntapi->sc_connect = __ntapi_sc_connect_v1;
+ __ntapi->sc_server_accept_connection = __ntapi_sc_server_accept_connection_v1;
+ __ntapi->sc_getsockname = __ntapi_sc_getsockname_v1;
+ }
+
+ /* internals */
+ internals->ntapi_img_sec_bss = &__ntapi_img_bss;
+ internals->subsystem = &__ntapi_rdata.img_sec_data.__session_name;
+
+ internals->tt_get_csr_port_handle_addr_by_logic = __GET_CSR_PORT_HANDLE_BY_LOGIC;
+ internals->csr_port_handle_addr = __GET_CSR_PORT_HANDLE_BY_LOGIC();
+
+ /* shadow copy for client libraries */
+ __ntapi->tt_aligned_block_memcpy(
+ (uintptr_t *)&___ntapi_shadow,
+ (uintptr_t *)&___ntapi,
+ sizeof(ntapi_vtbl));
+
+ /* done */
+ *pvtbl = &___ntapi_shadow;
+ at_locked_inc(&__ntapi_init_idx);
+
+ return NT_STATUS_SUCCESS;
+}
+
+
+static int32_t __fastcall __ntapi_init_pending(ntapi_vtbl ** pvtbl)
+{
+ return NT_STATUS_PENDING;
+}
+
+static int32_t __fastcall __ntapi_init_completed(ntapi_vtbl ** pvtbl)
+{
+ *pvtbl = __ntapi;
+ return NT_STATUS_SUCCESS;
+};
+
+
+__ntapi_api
+int32_t __fastcall ntapi_init(ntapi_vtbl ** pvtbl)
+{
+ return __ntapi_init_vtbl[__ntapi_init_idx](pvtbl);
+}
+
+
+ntapi_internals * __cdecl __ntapi_internals(void)
+{
+ return internals;
+}