/********************************************************/
/* ntapi: Native API core library */
/* Copyright (C) 2013--2017 Z. Gilboa */
/* Released under GPLv2 and GPLv3; see COPYING.NTAPI. */
/********************************************************/
#include <psxtypes/psxtypes.h>
#include <ntapi/nt_guid.h>
#include <ntapi/nt_port.h>
#include <ntapi/nt_string.h>
#include "ntapi_impl.h"
typedef wchar16_t __port_service_prefix[6];
static const __port_service_prefix __port_service_null = {0};
static const __port_service_prefix __port_service_prefixes[NT_PORT_TYPE_CAP][NT_PORT_SUBTYPE_CAP] = {
{{'s','v','c','a','n','y'}},
{{'n','t','c','t','t','y'}},
{{'v','m','o','u','n','t'}},
{{'d','a','e','m','o','n'}},
{{'s','y','m','l','n','k'}},
{{'n','t','p','r','o','c'}},
{{'s','e','m','c','t','l'}},
{{'s','e','m','s','v','c'}}};
static const nt_guid __port_guids[NT_PORT_TYPE_CAP][NT_PORT_SUBTYPE_CAP] = {
{NT_PORT_GUID_DEFAULT},
{NT_PORT_GUID_SUBSYSTEM},
{NT_PORT_GUID_VMOUNT},
{NT_PORT_GUID_DAEMON},
{NT_PORT_GUID_SYMLNK},
{NT_PORT_GUID_NTPROC},
{NT_PORT_GUID_SEMCTL},
{NT_PORT_GUID_SEMSVC}};
int32_t __stdcall __ntapi_tt_port_guid_from_type(
__out nt_guid * guid,
__in nt_port_type type,
__in nt_port_subtype subtype)
{
const nt_guid * src_guid;
if ((type >= NT_PORT_TYPE_CAP) || (subtype >= NT_PORT_SUBTYPE_CAP))
return NT_STATUS_INVALID_PARAMETER;
src_guid = &(__port_guids[type][subtype]);
__ntapi->tt_aligned_block_memcpy(
(uintptr_t *)guid,
(uintptr_t *)src_guid,
sizeof(nt_guid));
return NT_STATUS_SUCCESS;
}
int32_t __stdcall __ntapi_tt_port_type_from_guid(
__out nt_port_type * type,
__out nt_port_subtype * subtype,
__in const nt_guid * guid)
{
int itype;
int isubtype;
for (itype=0; itype<NT_PORT_TYPE_CAP; itype++) {
for (isubtype=0; isubtype<NT_PORT_SUBTYPE_CAP; isubtype++) {
if (!(__ntapi_tt_guid_compare(
&__port_guids[itype][isubtype],
guid))) {
*type = (nt_port_type)itype;
*subtype = (nt_port_subtype)isubtype;
return NT_STATUS_SUCCESS;
}
}
}
return NT_STATUS_NOT_FOUND;
}
int32_t __stdcall __ntapi_tt_port_generate_keys(
__out nt_port_keys * keys)
{
int32_t status;
nt_large_integer ticks;
nt_large_integer pcfreq;
nt_luid luid;
if ((status = __ntapi->zw_query_performance_counter(&ticks,&pcfreq)))
return status;
if ((status = __ntapi->zw_allocate_locally_unique_id(&luid)))
return status;
keys->key[0] = pe_get_current_process_id();
keys->key[1] = pe_get_current_thread_id();
keys->key[2] = ticks.ihigh;
keys->key[3] = ticks.ulow;
keys->key[4] = luid.high;
keys->key[5] = luid.low;
return NT_STATUS_SUCCESS;
}
void __stdcall __ntapi_tt_port_format_keys(
__in nt_port_keys * keys,
__out nt_port_name_keys * name_keys)
{
__ntapi->tt_uint32_to_hex_utf16(keys->key[0],name_keys->key_1st);
__ntapi->tt_uint32_to_hex_utf16(keys->key[1],name_keys->key_2nd);
__ntapi->tt_uint32_to_hex_utf16(keys->key[2],name_keys->key_3rd);
__ntapi->tt_uint32_to_hex_utf16(keys->key[3],name_keys->key_4th);
__ntapi->tt_uint32_to_hex_utf16(keys->key[4],name_keys->key_5th);
__ntapi->tt_uint32_to_hex_utf16(keys->key[5],name_keys->key_6th);
return;
}
void __stdcall __ntapi_tt_port_name_from_attr(
__out nt_port_name * name,
__in nt_port_attr * attr)
{
wchar16_t bno[] = __NT_BASED_NAMED_OBJECTS;
/* base named objects */
__ntapi->tt_memcpy_utf16(
name->base_named_objects,
bno,sizeof(bno));
/* service prefix */
if (attr && (attr->type < NT_PORT_TYPE_CAP) && (attr->subtype < NT_PORT_SUBTYPE_CAP))
__ntapi->tt_memcpy_utf16(
name->svc_prefix,
__port_service_prefixes[attr->type][attr->subtype],
sizeof(name->svc_prefix));
else
__ntapi->tt_memcpy_utf16(
name->svc_prefix,
__port_service_null,
sizeof(name->svc_prefix));
/* port guid */
__ntapi->tt_guid_to_string_utf16(
&attr->guid,
(nt_guid_str_utf16 *)&name->port_guid);
/* port name keys */
__ntapi_tt_port_format_keys(
&attr->keys,
&name->port_name_keys);
/* backslash and underscores */
name->backslash = '\\';
name->port_guid.uscore_guid = '_';
name->port_guid.uscore_keys = '_';
name->port_name_keys.uscore_1st = '_';
name->port_name_keys.uscore_2nd = '_';
name->port_name_keys.uscore_3rd = '_';
name->port_name_keys.uscore_4th = '_';
name->port_name_keys.uscore_5th = '_';
/* null termination */
name->null_termination = 0;
return;
}
static int32_t __tt_port_attr_from_name(
__out nt_port_attr * attr,
__in const nt_port_name * name)
{
int i;
int type;
int32_t status;
const wchar16_t bno[] = __NT_BASED_NAMED_OBJECTS;
/* base named objects */
if (__ntapi->tt_strncmp_utf16(
name->base_named_objects,
bno,sizeof(bno)))
return NT_STATUS_INVALID_PARAMETER;
/* service prefix */
for (i=0, type=-1; i<NT_PORT_TYPE_CAP && type<0; i++)
if (!(__ntapi->tt_strncmp_utf16(
name->svc_prefix,
__port_service_prefixes[i][0],
sizeof(__port_service_prefix))))
type = i;
if (type < 0)
return NT_STATUS_INVALID_PARAMETER;
/* port guid */
if ((status = __ntapi->tt_string_to_guid_utf16(
(nt_guid_str_utf16 *)&name->port_guid,
&attr->guid)))
return status;
/* port keys */
if ((status = __ntapi->tt_hex_utf16_to_uint32(
name->port_name_keys.key_1st,
&attr->keys.key[0])))
return status;
if ((status = __ntapi->tt_hex_utf16_to_uint32(
name->port_name_keys.key_2nd,
&attr->keys.key[1])))
return status;
if ((status = __ntapi->tt_hex_utf16_to_uint32(
name->port_name_keys.key_3rd,
&attr->keys.key[2])))
return status;
if ((status = __ntapi->tt_hex_utf16_to_uint32(
name->port_name_keys.key_4th,
&attr->keys.key[3])))
return status;
if ((status = __ntapi->tt_hex_utf16_to_uint32(
name->port_name_keys.key_5th,
&attr->keys.key[4])))
return status;
if ((status = __ntapi->tt_hex_utf16_to_uint32(
name->port_name_keys.key_6th,
&attr->keys.key[5])))
return status;
/* backslash and underscores */
if (name->backslash != '\\')
return NT_STATUS_INVALID_PARAMETER;
if (name->port_name_keys.uscore_1st != '_')
return NT_STATUS_INVALID_PARAMETER;
if (name->port_name_keys.uscore_2nd != '_')
return NT_STATUS_INVALID_PARAMETER;
if (name->port_name_keys.uscore_3rd != '_')
return NT_STATUS_INVALID_PARAMETER;
if (name->port_name_keys.uscore_4th != '_')
return NT_STATUS_INVALID_PARAMETER;
if (name->port_name_keys.uscore_5th != '_')
return NT_STATUS_INVALID_PARAMETER;
/* type */
attr->type = type;
attr->subtype = 0;
/* unknown defaults */
attr->ver_major = 0;
attr->ver_minor = 0;
attr->options = 0;
attr->flags = 0;
/* all done */
return NT_STATUS_SUCCESS;
}
int32_t __stdcall __ntapi_tt_port_attr_from_name(
__out nt_port_attr * attr,
__in const nt_port_name * name)
{
/* null termination */
if (name->null_termination)
return NT_STATUS_INVALID_PARAMETER;
return __tt_port_attr_from_name(
attr,name);
}
int32_t __stdcall __ntapi_tt_port_attr_from_string(
__out nt_port_attr * attr,
__in const nt_unicode_string * str)
{
if (str->strlen != ((size_t)&(((nt_port_name *)0)->null_termination)))
return NT_STATUS_INVALID_PARAMETER;
return __tt_port_attr_from_name(
attr,(const nt_port_name *)str->buffer);
}
int32_t __stdcall __ntapi_tt_port_attr_from_symlink(
__out nt_port_attr * attr,
__in void * symlink)
{
int32_t status;
size_t size;
nt_unicode_string * target;
uintptr_t buffer[512/sizeof(uintptr_t)];
target = (nt_unicode_string *)buffer;
target->strlen = 0;
target->maxlen = sizeof(buffer) - sizeof(nt_unicode_string);
target->buffer = (wchar16_t *)&target[1];
if ((status = __ntapi->zw_query_symbolic_link_object(
symlink,target,&size)))
return status;
if (target->strlen != ((size_t)&(((nt_port_name *)0)->null_termination)))
return NT_STATUS_INVALID_PARAMETER;
return __tt_port_attr_from_name(
attr,(const nt_port_name *)target->buffer);
}