|
|
9faf9a |
/********************************************************/
|
|
|
9faf9a |
/* ntapi: Native API core library */
|
|
|
64e606 |
/* Copyright (C) 2013--2021 SysDeer Technologies, LLC */
|
|
|
9faf9a |
/* Released under GPLv2 and GPLv3; see COPYING.NTAPI. */
|
|
|
9faf9a |
/********************************************************/
|
|
|
9faf9a |
|
|
|
9faf9a |
#include <psxtypes/psxtypes.h>
|
|
|
9faf9a |
#include <ntapi/nt_file.h>
|
|
|
9faf9a |
#include <ntapi/nt_string.h>
|
|
|
9faf9a |
#include <ntapi/nt_atomic.h>
|
|
|
9faf9a |
#include <ntapi/nt_port.h>
|
|
|
9faf9a |
#include <ntapi/nt_ipc.h>
|
|
|
9faf9a |
#include <ntapi/nt_sem.h>
|
|
|
9faf9a |
#include <ntapi/ntapi.h>
|
|
|
9faf9a |
#include "ntapi_impl.h"
|
|
|
9faf9a |
|
|
|
9faf9a |
static const nt_guid g_sempid = NT_IPC_GUID_SEMPID;
|
|
|
9faf9a |
static const wchar16_t p_sempid[6] = NT_IPC_OBJDIR_PREFIX_SEMPID;
|
|
|
9faf9a |
|
|
|
9faf9a |
static int32_t __semctl_get_service_attr(
|
|
|
9faf9a |
nt_rtdata * rtdata,
|
|
|
9faf9a |
nt_tty_service_info * semctl)
|
|
|
9faf9a |
{
|
|
|
9faf9a |
nt_iosb iosb;
|
|
|
9faf9a |
|
|
|
9faf9a |
/* inherited runtime data? */
|
|
|
9faf9a |
if (rtdata->semctl_keys[0]) {
|
|
|
9faf9a |
semctl->attr.ver_major = 0;
|
|
|
9faf9a |
semctl->attr.ver_minor = 0;
|
|
|
9faf9a |
semctl->attr.options = 0;
|
|
|
9faf9a |
semctl->attr.flags = 0;
|
|
|
9faf9a |
|
|
|
9faf9a |
semctl->attr.type = rtdata->semctl_type;
|
|
|
9faf9a |
semctl->attr.subtype = rtdata->semctl_subtype;
|
|
|
9faf9a |
|
|
|
9faf9a |
semctl->attr.keys.key[0] = rtdata->semctl_keys[0];
|
|
|
9faf9a |
semctl->attr.keys.key[1] = rtdata->semctl_keys[1];
|
|
|
9faf9a |
semctl->attr.keys.key[2] = rtdata->semctl_keys[2];
|
|
|
9faf9a |
semctl->attr.keys.key[3] = rtdata->semctl_keys[3];
|
|
|
9faf9a |
semctl->attr.keys.key[4] = rtdata->semctl_keys[4];
|
|
|
9faf9a |
semctl->attr.keys.key[5] = rtdata->semctl_keys[5];
|
|
|
9faf9a |
|
|
|
9faf9a |
__ntapi->tt_guid_copy(
|
|
|
9faf9a |
&semctl->attr.guid,
|
|
|
9faf9a |
&rtdata->semctl_guid);
|
|
|
9faf9a |
|
|
|
9faf9a |
return NT_STATUS_SUCCESS;
|
|
|
9faf9a |
}
|
|
|
9faf9a |
|
|
|
9faf9a |
/* obtain service info */
|
|
|
9faf9a |
return __ntapi->tty_query_information_service(
|
|
|
9faf9a |
0,&iosb,
|
|
|
9faf9a |
semctl,&(nt_guid)NT_PORT_GUID_SEMCTL,
|
|
|
9faf9a |
0,0);
|
|
|
9faf9a |
}
|
|
|
9faf9a |
|
|
|
9faf9a |
static int32_t __semctl_server_connect(
|
|
|
9faf9a |
nt_rtdata * rtdata,
|
|
|
9faf9a |
nt_tty_service_info * semctl)
|
|
|
9faf9a |
{
|
|
|
9faf9a |
int32_t status;
|
|
|
9faf9a |
|
|
|
9faf9a |
/* already cononected? */
|
|
|
9faf9a |
if (rtdata->hsemctl)
|
|
|
9faf9a |
return NT_STATUS_SUCCESS;
|
|
|
9faf9a |
|
|
|
9faf9a |
/* connect */
|
|
|
9faf9a |
if ((status = __ntapi->ipc_connect_by_attr(
|
|
|
9faf9a |
&rtdata->hsemctl,
|
|
|
1717a8 |
&semctl->attr,
|
|
|
1717a8 |
false)))
|
|
|
9faf9a |
return status;
|
|
|
9faf9a |
|
|
|
9faf9a |
/* update */
|
|
|
9faf9a |
rtdata->semctl_type = semctl->attr.type;
|
|
|
9faf9a |
rtdata->semctl_subtype = semctl->attr.subtype;
|
|
|
9faf9a |
|
|
|
9faf9a |
rtdata->semctl_keys[0] = semctl->attr.keys.key[0];
|
|
|
9faf9a |
rtdata->semctl_keys[1] = semctl->attr.keys.key[1];
|
|
|
9faf9a |
rtdata->semctl_keys[2] = semctl->attr.keys.key[2];
|
|
|
9faf9a |
rtdata->semctl_keys[3] = semctl->attr.keys.key[3];
|
|
|
9faf9a |
rtdata->semctl_keys[4] = semctl->attr.keys.key[4];
|
|
|
9faf9a |
rtdata->semctl_keys[5] = semctl->attr.keys.key[5];
|
|
|
9faf9a |
|
|
|
9faf9a |
__ntapi->tt_guid_copy(
|
|
|
9faf9a |
&rtdata->semctl_guid,
|
|
|
9faf9a |
&semctl->attr.guid);
|
|
|
9faf9a |
|
|
|
9faf9a |
return NT_STATUS_SUCCESS;
|
|
|
9faf9a |
}
|
|
|
9faf9a |
|
|
|
9faf9a |
static int32_t __sempid_symlink_set(
|
|
|
9faf9a |
nt_rtdata * rtdata,
|
|
|
9faf9a |
nt_tty_service_info * semctl)
|
|
|
9faf9a |
{
|
|
|
9faf9a |
int32_t status;
|
|
|
9faf9a |
void * hpiddir;
|
|
|
9faf9a |
nt_port_name svcname;
|
|
|
9faf9a |
nt_unicode_string str;
|
|
|
9faf9a |
|
|
|
9faf9a |
if (rtdata->hsempid)
|
|
|
9faf9a |
return NT_STATUS_SUCCESS;
|
|
|
9faf9a |
|
|
|
9faf9a |
if (!rtdata->hsempiddir) {
|
|
|
9faf9a |
if ((status = __ntapi->tt_open_ipc_object_directory(
|
|
|
9faf9a |
&hpiddir,
|
|
|
10276e |
NT_SEC_READ_CONTROL
|
|
|
10276e |
| NT_DIRECTORY_QUERY
|
|
|
10276e |
| NT_DIRECTORY_TRAVERSE
|
|
|
10276e |
| NT_DIRECTORY_CREATE_OBJECT
|
|
|
10276e |
| NT_DIRECTORY_CREATE_SUBDIRECTORY,
|
|
|
9faf9a |
p_sempid,&g_sempid)))
|
|
|
9faf9a |
return status;
|
|
|
9faf9a |
|
|
|
9faf9a |
if (at_locked_cas((intptr_t *)&rtdata->hsempiddir,0,(intptr_t)hpiddir))
|
|
|
9faf9a |
__ntapi->zw_close(hpiddir);
|
|
|
9faf9a |
}
|
|
|
9faf9a |
|
|
|
9faf9a |
__ntapi->tt_port_name_from_attr(
|
|
|
9faf9a |
&svcname,&semctl->attr);
|
|
|
9faf9a |
|
|
|
a73815 |
str.strlen = (uint16_t)(__offsetof(nt_port_name,null_termination));
|
|
|
9faf9a |
str.maxlen = sizeof(nt_port_name);
|
|
|
9faf9a |
str.buffer = svcname.base_named_objects;
|
|
|
9faf9a |
|
|
|
9faf9a |
return __ntapi->tt_create_ipc_object_directory_entry(
|
|
|
9faf9a |
&rtdata->hsempid,
|
|
|
9faf9a |
NT_SEC_STANDARD_RIGHTS_ALL,
|
|
|
9faf9a |
rtdata->hsempiddir,
|
|
|
9faf9a |
0,&str,
|
|
|
9faf9a |
pe_get_current_process_id());
|
|
|
9faf9a |
|
|
|
9faf9a |
}
|
|
|
9faf9a |
|
|
|
9faf9a |
static int32_t __stdcall __sem_open(
|
|
|
9faf9a |
void * hipc,
|
|
|
9faf9a |
nt_sem_info * sem,
|
|
|
9faf9a |
uint32_t access,
|
|
|
9faf9a |
nt_object_attributes * oa,
|
|
|
9faf9a |
nt_iosb * iosb,
|
|
|
9faf9a |
uint32_t share,
|
|
|
9faf9a |
uint32_t semslots,
|
|
|
9faf9a |
uint32_t key,
|
|
|
9faf9a |
uint32_t id,
|
|
|
9faf9a |
uint32_t opcode)
|
|
|
9faf9a |
{
|
|
|
9faf9a |
int32_t status;
|
|
|
9faf9a |
nt_tty_port_msg msg;
|
|
|
9faf9a |
nt_iosb siosb;
|
|
|
9faf9a |
nt_tty_service_info semctl;
|
|
|
9faf9a |
nt_runtime_data * rtdata;
|
|
|
9faf9a |
|
|
|
9faf9a |
/* init */
|
|
|
9faf9a |
rtdata = (__ntapi_internals())->rtdata;
|
|
|
9faf9a |
|
|
|
9faf9a |
/* semctl service attributes */
|
|
|
9faf9a |
if (!rtdata->hsempid)
|
|
|
9faf9a |
if ((status = __semctl_get_service_attr(rtdata,&semctl)))
|
|
|
9faf9a |
return status;
|
|
|
9faf9a |
|
|
|
9faf9a |
/* semctl server */
|
|
|
9faf9a |
if ((status = __semctl_server_connect(rtdata,&semctl)))
|
|
|
9faf9a |
return status;
|
|
|
9faf9a |
|
|
|
9faf9a |
/* sempid symlink */
|
|
|
9faf9a |
if ((status = __sempid_symlink_set(rtdata,&semctl)))
|
|
|
9faf9a |
return status;
|
|
|
9faf9a |
|
|
|
9faf9a |
/* hipc */
|
|
|
9faf9a |
if (!hipc && (opcode == NT_TTY_SEM_ALLOC))
|
|
|
9faf9a |
hipc = (__ntapi_internals())->rtdata->hsemctl;
|
|
|
9faf9a |
|
|
|
9faf9a |
/* obtain sem info */
|
|
|
9faf9a |
__ntapi->tt_aligned_block_memset(
|
|
|
9faf9a |
&msg,0,sizeof(msg));
|
|
|
9faf9a |
|
|
|
9faf9a |
if (!iosb)
|
|
|
9faf9a |
iosb = &siosb;
|
|
|
9faf9a |
|
|
|
9faf9a |
msg.header.msg_type = NT_LPC_NEW_MESSAGE;
|
|
|
9faf9a |
msg.header.data_size = sizeof(nt_sem_info_msg) - sizeof(msg.header);
|
|
|
9faf9a |
msg.header.msg_size = sizeof(msg);
|
|
|
9faf9a |
msg.ttyinfo.opcode = opcode;
|
|
|
9faf9a |
|
|
|
9faf9a |
msg.seminfo.semkey = (int32_t)key;
|
|
|
9faf9a |
msg.seminfo.semid = (int32_t)id;
|
|
|
9faf9a |
msg.seminfo.semslots = semslots;
|
|
|
9faf9a |
|
|
|
9faf9a |
msg.seminfo.ntattr = oa->obj_attr;
|
|
|
9faf9a |
msg.seminfo.ntaccess = access;
|
|
|
9faf9a |
msg.seminfo.ntshare = share;
|
|
|
9faf9a |
|
|
|
9faf9a |
if ((status = __ntapi->zw_request_wait_reply_port(hipc,&msg,&msg)))
|
|
|
9faf9a |
return status;
|
|
|
9faf9a |
else if (msg.ttyinfo.status)
|
|
|
9faf9a |
return msg.ttyinfo.status;
|
|
|
9faf9a |
|
|
|
9faf9a |
iosb->info = sizeof(msg.svcinfo);
|
|
|
9faf9a |
iosb->status = NT_STATUS_SUCCESS;
|
|
|
9faf9a |
|
|
|
9faf9a |
/* new semaphore? */
|
|
|
9faf9a |
if (opcode == NT_TTY_SEM_ALLOC)
|
|
|
9faf9a |
if ((status = __ntapi->ipc_connect_by_attr(
|
|
|
1717a8 |
&hipc,&msg.svcinfo.attr,
|
|
|
1717a8 |
false)))
|
|
|
9faf9a |
return status;
|
|
|
9faf9a |
|
|
|
9faf9a |
/* all done */
|
|
|
9faf9a |
__ntapi->tt_aligned_block_memset(
|
|
|
9faf9a |
(uintptr_t *)sem,
|
|
|
9faf9a |
0,sizeof(*sem));
|
|
|
9faf9a |
|
|
|
9faf9a |
sem->semkey = msg.svcinfo.key;
|
|
|
9faf9a |
sem->semid = msg.svcinfo.id;
|
|
|
9faf9a |
|
|
|
9faf9a |
sem->hport = hipc;
|
|
|
9faf9a |
|
|
|
9faf9a |
return NT_STATUS_SUCCESS;
|
|
|
9faf9a |
}
|
|
|
9faf9a |
|
|
|
9faf9a |
|
|
|
2903da |
int32_t __stdcall __ntapi_sem_create(
|
|
|
9faf9a |
__in void * hport,
|
|
|
9faf9a |
__out nt_sem_info * sem,
|
|
|
9faf9a |
__in uint32_t access,
|
|
|
9faf9a |
__in nt_object_attributes * oa,
|
|
|
9faf9a |
__out nt_iosb * iosb,
|
|
|
9faf9a |
__in uint32_t share,
|
|
|
9faf9a |
__in uint32_t nslots)
|
|
|
9faf9a |
{
|
|
|
9faf9a |
uint32_t key;
|
|
|
9faf9a |
|
|
|
9faf9a |
/* validate */
|
|
|
9faf9a |
if (!oa->root_dir)
|
|
|
9faf9a |
return NT_STATUS_DIRECTORY_SERVICE_REQUIRED;
|
|
|
9faf9a |
|
|
|
9faf9a |
if (oa->obj_name && !oa->obj_name->strlen) {
|
|
|
9faf9a |
key = 0;
|
|
|
9faf9a |
|
|
|
9faf9a |
} else if (oa->obj_name) {
|
|
|
9faf9a |
if (oa->obj_name->strlen != 8 * sizeof(wchar16_t))
|
|
|
9faf9a |
return NT_STATUS_OBJECT_NAME_INVALID;
|
|
|
9faf9a |
|
|
|
9faf9a |
if (__ntapi->tt_hex_utf16_to_uint32(oa->obj_name->buffer,&key))
|
|
|
9faf9a |
return NT_STATUS_OBJECT_NAME_INVALID;
|
|
|
9faf9a |
|
|
|
9faf9a |
} else {
|
|
|
9faf9a |
key = 0;
|
|
|
9faf9a |
}
|
|
|
9faf9a |
|
|
|
9faf9a |
/* open semaphore */
|
|
|
9faf9a |
return __sem_open(
|
|
|
9faf9a |
hport,sem,access,
|
|
|
9faf9a |
oa,iosb,share,nslots,
|
|
|
9faf9a |
key,0,NT_TTY_SEM_ALLOC);
|
|
|
9faf9a |
}
|
|
|
9faf9a |
|
|
|
9faf9a |
|
|
|
9faf9a |
int32_t __stdcall __ntapi_sem_open(
|
|
|
9faf9a |
__in void * hport,
|
|
|
9faf9a |
__out nt_sem_info * sem,
|
|
|
9faf9a |
__in uint32_t access,
|
|
|
9faf9a |
__in nt_object_attributes * oa,
|
|
|
9faf9a |
__out nt_iosb * iosb,
|
|
|
9faf9a |
__in uint32_t share,
|
|
|
9faf9a |
__in uint32_t nslots)
|
|
|
9faf9a |
{
|
|
|
edb085 |
int32_t status;
|
|
|
edb085 |
uint32_t key;
|
|
|
edb085 |
uint32_t id;
|
|
|
edb085 |
void * hsymlink;
|
|
|
edb085 |
nt_oa ipcoa;
|
|
|
edb085 |
void * hipc;
|
|
|
edb085 |
nt_rtdata * rtdata;
|
|
|
edb085 |
nt_tty_service_info semctl;
|
|
|
edb085 |
|
|
|
edb085 |
/* init */
|
|
|
edb085 |
rtdata = (__ntapi_internals())->rtdata;
|
|
|
9faf9a |
|
|
|
9faf9a |
/* validate */
|
|
|
9faf9a |
if (!oa->root_dir)
|
|
|
9faf9a |
return NT_STATUS_DIRECTORY_SERVICE_REQUIRED;
|
|
|
9faf9a |
|
|
|
9faf9a |
if (!oa->obj_name)
|
|
|
9faf9a |
return NT_STATUS_INVALID_PARAMETER;
|
|
|
9faf9a |
|
|
|
9faf9a |
if (oa->obj_name->strlen != 8 * sizeof(wchar16_t))
|
|
|
9faf9a |
return NT_STATUS_OBJECT_NAME_INVALID;
|
|
|
9faf9a |
|
|
|
9faf9a |
if (__ntapi->tt_hex_utf16_to_uint32(oa->obj_name->buffer,&key))
|
|
|
9faf9a |
return NT_STATUS_OBJECT_NAME_INVALID;
|
|
|
9faf9a |
|
|
|
9faf9a |
/* open symlink */
|
|
|
9faf9a |
ipcoa.len = sizeof(ipcoa);
|
|
|
9faf9a |
ipcoa.root_dir = oa->root_dir;
|
|
|
9faf9a |
ipcoa.obj_name = oa->obj_name;
|
|
|
9faf9a |
ipcoa.obj_attr = 0;
|
|
|
9faf9a |
ipcoa.sec_desc = oa->sec_desc;
|
|
|
9faf9a |
ipcoa.sec_qos = oa->sec_qos;
|
|
|
9faf9a |
|
|
|
9faf9a |
status = __ntapi->zw_open_symbolic_link_object(
|
|
|
9faf9a |
&hsymlink,
|
|
|
10276e |
NT_SYMBOLIC_LINK_QUERY,
|
|
|
9faf9a |
&ipcoa);
|
|
|
9faf9a |
|
|
|
9faf9a |
switch (status) {
|
|
|
9faf9a |
case NT_STATUS_SUCCESS:
|
|
|
9faf9a |
break;
|
|
|
9faf9a |
|
|
|
9faf9a |
case NT_STATUS_OBJECT_NAME_NOT_FOUND:
|
|
|
9faf9a |
case NT_STATUS_OBJECT_PATH_NOT_FOUND:
|
|
|
9faf9a |
if (oa->obj_attr & NT_OBJ_OPENIF)
|
|
|
9faf9a |
return __sem_open(
|
|
|
9faf9a |
hport,sem,access,
|
|
|
9faf9a |
oa,iosb,share,nslots,
|
|
|
9faf9a |
key,0,NT_TTY_SEM_ALLOC);
|
|
|
9faf9a |
else
|
|
|
9faf9a |
return status;
|
|
|
9faf9a |
|
|
|
9faf9a |
default:
|
|
|
9faf9a |
return status;
|
|
|
9faf9a |
}
|
|
|
9faf9a |
|
|
|
edb085 |
/* semctl service attributes */
|
|
|
edb085 |
if (!rtdata->hsempid)
|
|
|
edb085 |
if ((status = __semctl_get_service_attr(rtdata,&semctl)))
|
|
|
edb085 |
return status;
|
|
|
edb085 |
|
|
|
edb085 |
/* semctl server */
|
|
|
edb085 |
if ((status = __semctl_server_connect(rtdata,&semctl)))
|
|
|
edb085 |
return status;
|
|
|
edb085 |
|
|
|
edb085 |
/* sempid symlink */
|
|
|
edb085 |
if ((status = __sempid_symlink_set(rtdata,&semctl)))
|
|
|
edb085 |
return status;
|
|
|
edb085 |
|
|
|
9faf9a |
/* ipc connect */
|
|
|
9faf9a |
status = __ntapi->ipc_connect_by_symlink(
|
|
|
1717a8 |
&hipc,hsymlink,false);
|
|
|
9faf9a |
|
|
|
9faf9a |
__ntapi->zw_close(
|
|
|
9faf9a |
hsymlink);
|
|
|
9faf9a |
|
|
|
9faf9a |
if (status)
|
|
|
9faf9a |
return status;
|
|
|
9faf9a |
|
|
|
9faf9a |
/* open by id? */
|
|
|
9faf9a |
if (oa->obj_attr & NT_OBJ_OPENLINK) {
|
|
|
9faf9a |
id = key;
|
|
|
9faf9a |
key = 0;
|
|
|
9faf9a |
} else {
|
|
|
9faf9a |
id = 0;
|
|
|
9faf9a |
}
|
|
|
9faf9a |
|
|
|
9faf9a |
return __sem_open(
|
|
|
9faf9a |
hipc,sem,access,
|
|
|
9faf9a |
oa,iosb,share,nslots,
|
|
|
9faf9a |
key,id,NT_TTY_SEM_OPEN);
|
|
|
9faf9a |
}
|