diff options
Diffstat (limited to 'src/sem/ntapi_sem_query.c')
-rw-r--r-- | src/sem/ntapi_sem_query.c | 130 |
1 files changed, 130 insertions, 0 deletions
diff --git a/src/sem/ntapi_sem_query.c b/src/sem/ntapi_sem_query.c new file mode 100644 index 0000000..816d50d --- /dev/null +++ b/src/sem/ntapi_sem_query.c @@ -0,0 +1,130 @@ +/********************************************************/ +/* 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_file.h> +#include <ntapi/nt_string.h> +#include <ntapi/nt_atomic.h> +#include <ntapi/nt_port.h> +#include <ntapi/nt_ipc.h> +#include <ntapi/nt_sem.h> +#include <ntapi/ntapi.h> +#include "ntapi_impl.h" + +static int32_t __sem_query_return( + intptr_t * hlock, + int32_t status, + int32_t cmd) +{ + if (cmd == NT_SEM_CMD_GETALL) + at_store(hlock,0); + + return status; +} + +int32_t __stdcall __ntapi_sem_query( + __in nt_sem_info * sem, + __out nt_io_status_block * iosb, + __out void * sem_info, + __in uint32_t sem_info_length, + __in int32_t sem_ipc_cmd) +{ + int32_t status; + void * hsection; + void * secaddr; + size_t secsize; + nt_sem_info_msg msg; + intptr_t * hlock; + + /* validate */ + if (!iosb) + return NT_STATUS_INVALID_PARAMETER; + + else if (!sem_info) + return NT_STATUS_INVALID_PARAMETER; + + else if (!sem_info_length) + return NT_STATUS_INVALID_PARAMETER; + + else if (sem_ipc_cmd != NT_SEM_CMD_GETALL) + if (sem_info_length != sizeof(nt_sem_info)) + return NT_STATUS_INFO_LENGTH_MISMATCH; + + /* section */ + hsection = 0; + secaddr = 0; + secsize = 0; + + if (sem_ipc_cmd == NT_SEM_CMD_GETALL) { + if (sem->section_addr) { + hsection = sem->section; + secaddr = sem->section_addr; + secsize = sem->section_size; + + } else if ((status = __ntapi->ipc_init_section_by_port( + sem->hport,&hsection, + &secaddr,&secsize))) + return status; + + /* lock */ + hlock = &(__ntapi_internals()->hlock); + + if (at_locked_cas(hlock,0,1)) + return NT_STATUS_RESOURCE_NOT_OWNED; + } + + /* msg */ + __ntapi->tt_aligned_block_memset( + &msg,0,sizeof(msg)); + + msg.header.msg_type = NT_LPC_NEW_MESSAGE; + msg.header.data_size = sizeof(msg.data); + msg.header.msg_size = sizeof(msg); + msg.data.ttyinfo.opcode = NT_TTY_SEM_QUERY; + + msg.data.seminfo.semcmd = sem_ipc_cmd; + msg.data.seminfo.semkey = sem->semkey; + msg.data.seminfo.semid = sem->semid; + msg.data.seminfo.semnum = sem->semnum; + msg.data.seminfo.section_addr = secaddr; + msg.data.seminfo.section_size = secsize; + + if ((status = __ntapi->zw_request_wait_reply_port(sem->hport,&msg,&msg))) + return __sem_query_return(hlock,status,sem_ipc_cmd); + else if (msg.data.ttyinfo.status) + return __sem_query_return(hlock,msg.data.ttyinfo.status,sem_ipc_cmd); + + /* reply */ + if (sem_ipc_cmd == NT_SEM_CMD_GETALL) { + if (msg.data.seminfo.section_size > sem_info_length) + return __sem_query_return( + hlock, + NT_STATUS_BUFFER_TOO_SMALL, + sem_ipc_cmd); + + __ntapi->tt_generic_memcpy( + sem_info,secaddr, + msg.data.seminfo.section_size); + + at_store(hlock,0); + + iosb->status = NT_STATUS_SUCCESS; + iosb->info = msg.data.seminfo.section_size; + } else { + if (msg.header.data_size != sizeof(msg.data)) + return NT_STATUS_UNEXPECTED_IO_ERROR; + + __ntapi->tt_generic_memcpy( + sem_info, + &msg.data.seminfo, + sizeof(msg.data.seminfo)); + + iosb->status = NT_STATUS_SUCCESS; + iosb->info = sizeof(msg.data.seminfo); + } + + return NT_STATUS_SUCCESS; +} |