| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| static const nt_guid g_sempid = NT_IPC_GUID_SEMPID; |
| static const wchar16_t p_sempid[6] = NT_IPC_OBJDIR_PREFIX_SEMPID; |
| |
| static int32_t __semctl_get_service_attr( |
| nt_rtdata * rtdata, |
| nt_tty_service_info * semctl) |
| { |
| nt_iosb iosb; |
| |
| |
| if (rtdata->semctl_keys[0]) { |
| semctl->attr.ver_major = 0; |
| semctl->attr.ver_minor = 0; |
| semctl->attr.options = 0; |
| semctl->attr.flags = 0; |
| |
| semctl->attr.type = rtdata->semctl_type; |
| semctl->attr.subtype = rtdata->semctl_subtype; |
| |
| semctl->attr.keys.key[0] = rtdata->semctl_keys[0]; |
| semctl->attr.keys.key[1] = rtdata->semctl_keys[1]; |
| semctl->attr.keys.key[2] = rtdata->semctl_keys[2]; |
| semctl->attr.keys.key[3] = rtdata->semctl_keys[3]; |
| semctl->attr.keys.key[4] = rtdata->semctl_keys[4]; |
| semctl->attr.keys.key[5] = rtdata->semctl_keys[5]; |
| |
| __ntapi->tt_guid_copy( |
| &semctl->attr.guid, |
| &rtdata->semctl_guid); |
| |
| return NT_STATUS_SUCCESS; |
| } |
| |
| |
| return __ntapi->tty_query_information_service( |
| 0,&iosb, |
| semctl,&(nt_guid)NT_PORT_GUID_SEMCTL, |
| 0,0); |
| } |
| |
| static int32_t __semctl_server_connect( |
| nt_rtdata * rtdata, |
| nt_tty_service_info * semctl) |
| { |
| int32_t status; |
| |
| |
| if (rtdata->hsemctl) |
| return NT_STATUS_SUCCESS; |
| |
| |
| if ((status = __ntapi->ipc_connect_by_attr( |
| &rtdata->hsemctl, |
| &semctl->attr))) |
| return status; |
| |
| |
| rtdata->semctl_type = semctl->attr.type; |
| rtdata->semctl_subtype = semctl->attr.subtype; |
| |
| rtdata->semctl_keys[0] = semctl->attr.keys.key[0]; |
| rtdata->semctl_keys[1] = semctl->attr.keys.key[1]; |
| rtdata->semctl_keys[2] = semctl->attr.keys.key[2]; |
| rtdata->semctl_keys[3] = semctl->attr.keys.key[3]; |
| rtdata->semctl_keys[4] = semctl->attr.keys.key[4]; |
| rtdata->semctl_keys[5] = semctl->attr.keys.key[5]; |
| |
| __ntapi->tt_guid_copy( |
| &rtdata->semctl_guid, |
| &semctl->attr.guid); |
| |
| return NT_STATUS_SUCCESS; |
| } |
| |
| static int32_t __sempid_symlink_set( |
| nt_rtdata * rtdata, |
| nt_tty_service_info * semctl) |
| { |
| int32_t status; |
| void * hpiddir; |
| nt_port_name svcname; |
| nt_unicode_string str; |
| |
| if (rtdata->hsempid) |
| return NT_STATUS_SUCCESS; |
| |
| if (!rtdata->hsempiddir) { |
| if ((status = __ntapi->tt_open_ipc_object_directory( |
| &hpiddir, |
| NT_SEC_READ_CONTROL |
| | NT_DIRECTORY_QUERY |
| | NT_DIRECTORY_TRAVERSE |
| | NT_DIRECTORY_CREATE_OBJECT |
| | NT_DIRECTORY_CREATE_SUBDIRECTORY, |
| p_sempid,&g_sempid))) |
| return status; |
| |
| if (at_locked_cas((intptr_t *)&rtdata->hsempiddir,0,(intptr_t)hpiddir)) |
| __ntapi->zw_close(hpiddir); |
| } |
| |
| __ntapi->tt_port_name_from_attr( |
| &svcname,&semctl->attr); |
| |
| str.strlen = (uint16_t)(__offsetof(nt_port_name,null_termination)); |
| str.maxlen = sizeof(nt_port_name); |
| str.buffer = svcname.base_named_objects; |
| |
| return __ntapi->tt_create_ipc_object_directory_entry( |
| &rtdata->hsempid, |
| NT_SEC_STANDARD_RIGHTS_ALL, |
| rtdata->hsempiddir, |
| 0,&str, |
| pe_get_current_process_id()); |
| |
| } |
| |
| static int32_t __stdcall __sem_open( |
| void * hipc, |
| nt_sem_info * sem, |
| uint32_t access, |
| nt_object_attributes * oa, |
| nt_iosb * iosb, |
| uint32_t share, |
| uint32_t semslots, |
| uint32_t key, |
| uint32_t id, |
| uint32_t opcode) |
| { |
| int32_t status; |
| nt_tty_port_msg msg; |
| nt_iosb siosb; |
| nt_tty_service_info semctl; |
| nt_runtime_data * rtdata; |
| |
| |
| rtdata = (__ntapi_internals())->rtdata; |
| |
| |
| if (!rtdata->hsempid) |
| if ((status = __semctl_get_service_attr(rtdata,&semctl))) |
| return status; |
| |
| |
| if ((status = __semctl_server_connect(rtdata,&semctl))) |
| return status; |
| |
| |
| if ((status = __sempid_symlink_set(rtdata,&semctl))) |
| return status; |
| |
| |
| if (!hipc && (opcode == NT_TTY_SEM_ALLOC)) |
| hipc = (__ntapi_internals())->rtdata->hsemctl; |
| |
| |
| __ntapi->tt_aligned_block_memset( |
| &msg,0,sizeof(msg)); |
| |
| if (!iosb) |
| iosb = &siosb; |
| |
| msg.header.msg_type = NT_LPC_NEW_MESSAGE; |
| msg.header.data_size = sizeof(nt_sem_info_msg) - sizeof(msg.header); |
| msg.header.msg_size = sizeof(msg); |
| msg.ttyinfo.opcode = opcode; |
| |
| msg.seminfo.semkey = (int32_t)key; |
| msg.seminfo.semid = (int32_t)id; |
| msg.seminfo.semslots = semslots; |
| |
| msg.seminfo.ntattr = oa->obj_attr; |
| msg.seminfo.ntaccess = access; |
| msg.seminfo.ntshare = share; |
| |
| if ((status = __ntapi->zw_request_wait_reply_port(hipc,&msg,&msg))) |
| return status; |
| else if (msg.ttyinfo.status) |
| return msg.ttyinfo.status; |
| |
| iosb->info = sizeof(msg.svcinfo); |
| iosb->status = NT_STATUS_SUCCESS; |
| |
| |
| if (opcode == NT_TTY_SEM_ALLOC) |
| if ((status = __ntapi->ipc_connect_by_attr( |
| &hipc,&msg.svcinfo.attr))) |
| return status; |
| |
| |
| __ntapi->tt_aligned_block_memset( |
| (uintptr_t *)sem, |
| 0,sizeof(*sem)); |
| |
| sem->semkey = msg.svcinfo.key; |
| sem->semid = msg.svcinfo.id; |
| |
| sem->hport = hipc; |
| |
| return NT_STATUS_SUCCESS; |
| } |
| |
| |
| int32_t __stdcall __ntapi_sem_create( |
| __in void * hport, |
| __out nt_sem_info * sem, |
| __in uint32_t access, |
| __in nt_object_attributes * oa, |
| __out nt_iosb * iosb, |
| __in uint32_t share, |
| __in uint32_t nslots) |
| { |
| uint32_t key; |
| |
| |
| if (!oa->root_dir) |
| return NT_STATUS_DIRECTORY_SERVICE_REQUIRED; |
| |
| if (oa->obj_name && !oa->obj_name->strlen) { |
| key = 0; |
| |
| } else if (oa->obj_name) { |
| if (oa->obj_name->strlen != 8 * sizeof(wchar16_t)) |
| return NT_STATUS_OBJECT_NAME_INVALID; |
| |
| if (__ntapi->tt_hex_utf16_to_uint32(oa->obj_name->buffer,&key)) |
| return NT_STATUS_OBJECT_NAME_INVALID; |
| |
| } else { |
| key = 0; |
| } |
| |
| |
| return __sem_open( |
| hport,sem,access, |
| oa,iosb,share,nslots, |
| key,0,NT_TTY_SEM_ALLOC); |
| } |
| |
| |
| int32_t __stdcall __ntapi_sem_open( |
| __in void * hport, |
| __out nt_sem_info * sem, |
| __in uint32_t access, |
| __in nt_object_attributes * oa, |
| __out nt_iosb * iosb, |
| __in uint32_t share, |
| __in uint32_t nslots) |
| { |
| int32_t status; |
| uint32_t key; |
| uint32_t id; |
| void * hsymlink; |
| nt_oa ipcoa; |
| void * hipc; |
| nt_rtdata * rtdata; |
| nt_tty_service_info semctl; |
| |
| |
| rtdata = (__ntapi_internals())->rtdata; |
| |
| |
| if (!oa->root_dir) |
| return NT_STATUS_DIRECTORY_SERVICE_REQUIRED; |
| |
| if (!oa->obj_name) |
| return NT_STATUS_INVALID_PARAMETER; |
| |
| if (oa->obj_name->strlen != 8 * sizeof(wchar16_t)) |
| return NT_STATUS_OBJECT_NAME_INVALID; |
| |
| if (__ntapi->tt_hex_utf16_to_uint32(oa->obj_name->buffer,&key)) |
| return NT_STATUS_OBJECT_NAME_INVALID; |
| |
| |
| ipcoa.len = sizeof(ipcoa); |
| ipcoa.root_dir = oa->root_dir; |
| ipcoa.obj_name = oa->obj_name; |
| ipcoa.obj_attr = 0; |
| ipcoa.sec_desc = oa->sec_desc; |
| ipcoa.sec_qos = oa->sec_qos; |
| |
| status = __ntapi->zw_open_symbolic_link_object( |
| &hsymlink, |
| NT_SYMBOLIC_LINK_QUERY, |
| &ipcoa); |
| |
| switch (status) { |
| case NT_STATUS_SUCCESS: |
| break; |
| |
| case NT_STATUS_OBJECT_NAME_NOT_FOUND: |
| case NT_STATUS_OBJECT_PATH_NOT_FOUND: |
| if (oa->obj_attr & NT_OBJ_OPENIF) |
| return __sem_open( |
| hport,sem,access, |
| oa,iosb,share,nslots, |
| key,0,NT_TTY_SEM_ALLOC); |
| else |
| return status; |
| |
| default: |
| return status; |
| } |
| |
| |
| if (!rtdata->hsempid) |
| if ((status = __semctl_get_service_attr(rtdata,&semctl))) |
| return status; |
| |
| |
| if ((status = __semctl_server_connect(rtdata,&semctl))) |
| return status; |
| |
| |
| if ((status = __sempid_symlink_set(rtdata,&semctl))) |
| return status; |
| |
| |
| status = __ntapi->ipc_connect_by_symlink( |
| &hipc,hsymlink); |
| |
| __ntapi->zw_close( |
| hsymlink); |
| |
| if (status) |
| return status; |
| |
| |
| if (oa->obj_attr & NT_OBJ_OPENLINK) { |
| id = key; |
| key = 0; |
| } else { |
| id = 0; |
| } |
| |
| return __sem_open( |
| hipc,sem,access, |
| oa,iosb,share,nslots, |
| key,id,NT_TTY_SEM_OPEN); |
| } |