| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| static const nt_guid g_msqpid = NT_IPC_GUID_MSQPID; |
| static const wchar16_t p_msqpid[6] = NT_IPC_OBJDIR_PREFIX_MSQPID; |
| |
| static int32_t __msqctl_get_service_attr( |
| nt_rtdata * rtdata, |
| nt_tty_service_info * msqctl) |
| { |
| nt_iosb iosb; |
| |
| |
| if (rtdata->msqctl_keys[0]) { |
| msqctl->attr.ver_major = 0; |
| msqctl->attr.ver_minor = 0; |
| msqctl->attr.options = 0; |
| msqctl->attr.flags = 0; |
| |
| msqctl->attr.type = rtdata->msqctl_type; |
| msqctl->attr.subtype = rtdata->msqctl_subtype; |
| |
| msqctl->attr.keys.key[0] = rtdata->msqctl_keys[0]; |
| msqctl->attr.keys.key[1] = rtdata->msqctl_keys[1]; |
| msqctl->attr.keys.key[2] = rtdata->msqctl_keys[2]; |
| msqctl->attr.keys.key[3] = rtdata->msqctl_keys[3]; |
| msqctl->attr.keys.key[4] = rtdata->msqctl_keys[4]; |
| msqctl->attr.keys.key[5] = rtdata->msqctl_keys[5]; |
| |
| __ntapi->tt_guid_copy( |
| &msqctl->attr.guid, |
| &rtdata->msqctl_guid); |
| |
| return NT_STATUS_SUCCESS; |
| } |
| |
| |
| return __ntapi->tty_query_information_service( |
| 0,&iosb,msqctl, |
| &(nt_guid)NT_PORT_GUID_MSQCTL, |
| 0,0); |
| } |
| |
| static int32_t __msqctl_server_connect( |
| nt_rtdata * rtdata, |
| nt_tty_service_info * msqctl) |
| { |
| int32_t status; |
| |
| |
| if (rtdata->hmsqctl) |
| return NT_STATUS_SUCCESS; |
| |
| |
| if ((status = __ntapi->ipc_connect_by_attr( |
| &rtdata->hmsqctl, |
| &msqctl->attr, |
| false))) |
| return status; |
| |
| |
| rtdata->msqctl_type = msqctl->attr.type; |
| rtdata->msqctl_subtype = msqctl->attr.subtype; |
| |
| rtdata->msqctl_keys[0] = msqctl->attr.keys.key[0]; |
| rtdata->msqctl_keys[1] = msqctl->attr.keys.key[1]; |
| rtdata->msqctl_keys[2] = msqctl->attr.keys.key[2]; |
| rtdata->msqctl_keys[3] = msqctl->attr.keys.key[3]; |
| rtdata->msqctl_keys[4] = msqctl->attr.keys.key[4]; |
| rtdata->msqctl_keys[5] = msqctl->attr.keys.key[5]; |
| |
| __ntapi->tt_guid_copy( |
| &rtdata->msqctl_guid, |
| &msqctl->attr.guid); |
| |
| return NT_STATUS_SUCCESS; |
| } |
| |
| static int32_t __msqpid_symlink_set( |
| nt_rtdata * rtdata, |
| nt_tty_service_info * msqctl) |
| { |
| int32_t status; |
| void * hpiddir; |
| nt_port_name svcname; |
| nt_unicode_string str; |
| |
| if (rtdata->hmsqpid) |
| return NT_STATUS_SUCCESS; |
| |
| if (!rtdata->hmsqpiddir) { |
| 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_msqpid,&g_msqpid))) |
| return status; |
| |
| if (at_locked_cas((intptr_t *)&rtdata->hmsqpiddir,0,(intptr_t)hpiddir)) |
| __ntapi->zw_close(hpiddir); |
| } |
| |
| __ntapi->tt_port_name_from_attr( |
| &svcname,&msqctl->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->hmsqpid, |
| NT_SEC_STANDARD_RIGHTS_ALL, |
| rtdata->hmsqpiddir, |
| 0,&str, |
| pe_get_current_process_id()); |
| |
| } |
| |
| static int32_t __stdcall __msq_open( |
| void * hipc, |
| nt_msq_info * msq, |
| uint32_t access, |
| nt_object_attributes * oa, |
| nt_iosb * iosb, |
| uint32_t share, |
| uint32_t msqslots, |
| uint32_t key, |
| uint32_t id, |
| uint32_t opcode) |
| { |
| int32_t status; |
| nt_tty_port_msg msg; |
| nt_iosb siosb; |
| nt_tty_service_info msqctl; |
| nt_runtime_data * rtdata; |
| |
| |
| rtdata = (__ntapi_internals())->rtdata; |
| |
| |
| if (!rtdata->hmsqpid) |
| if ((status = __msqctl_get_service_attr(rtdata,&msqctl))) |
| return status; |
| |
| |
| if ((status = __msqctl_server_connect(rtdata,&msqctl))) |
| return status; |
| |
| |
| if ((status = __msqpid_symlink_set(rtdata,&msqctl))) |
| return status; |
| |
| |
| if (!hipc && (opcode == NT_TTY_MSQ_ALLOC)) |
| hipc = (__ntapi_internals())->rtdata->hmsqctl; |
| |
| |
| __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_msq_info_msg) - sizeof(msg.header); |
| msg.header.msg_size = sizeof(msg); |
| msg.ttyinfo.opcode = opcode; |
| |
| msg.msqinfo.msqkey = (int32_t)key; |
| msg.msqinfo.msqid = (int32_t)id; |
| msg.msqinfo.msqslots = msqslots; |
| |
| msg.msqinfo.ntattr = oa->obj_attr; |
| msg.msqinfo.ntaccess = access; |
| msg.msqinfo.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_MSQ_ALLOC) |
| if ((status = __ntapi->ipc_connect_by_attr( |
| &hipc,&msg.svcinfo.attr, |
| false))) |
| return status; |
| |
| |
| __ntapi->tt_aligned_block_memset( |
| (uintptr_t *)msq, |
| 0,sizeof(*msq)); |
| |
| msq->msqkey = msg.svcinfo.key; |
| msq->msqid = msg.svcinfo.id; |
| |
| msq->hport = hipc; |
| |
| return NT_STATUS_SUCCESS; |
| } |
| |
| |
| int32_t __stdcall __ntapi_msq_create( |
| __in void * hport, |
| __out nt_msq_info * msq, |
| __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 __msq_open( |
| hport,msq,access, |
| oa,iosb,share,nslots, |
| key,0,NT_TTY_MSQ_ALLOC); |
| } |
| |
| |
| int32_t __stdcall __ntapi_msq_open( |
| __in void * hport, |
| __out nt_msq_info * msq, |
| __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 msqctl; |
| |
| |
| 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 __msq_open( |
| hport,msq,access, |
| oa,iosb,share,nslots, |
| key,0,NT_TTY_MSQ_ALLOC); |
| else |
| return status; |
| |
| default: |
| return status; |
| } |
| |
| |
| if (!rtdata->hmsqpid) |
| if ((status = __msqctl_get_service_attr(rtdata,&msqctl))) |
| return status; |
| |
| |
| if ((status = __msqctl_server_connect(rtdata,&msqctl))) |
| return status; |
| |
| |
| if ((status = __msqpid_symlink_set(rtdata,&msqctl))) |
| return status; |
| |
| |
| status = __ntapi->ipc_connect_by_symlink( |
| &hipc,hsymlink,false); |
| |
| __ntapi->zw_close( |
| hsymlink); |
| |
| if (status) |
| return status; |
| |
| |
| if (oa->obj_attr & NT_OBJ_OPENLINK) { |
| id = key; |
| key = 0; |
| } else { |
| id = 0; |
| } |
| |
| return __msq_open( |
| hipc,msq,access, |
| oa,iosb,share,nslots, |
| key,id,NT_TTY_MSQ_OPEN); |
| } |