/********************************************************/ /* ntapi: Native API core library */ /* Copyright (C) 2013--2021 Z. Gilboa */ /* Released under GPLv2 and GPLv3; see COPYING.NTAPI. */ /********************************************************/ #include #include #include #include #include #include #include #include #include "ntapi_impl.h" static const nt_guid g_aflpid = NT_IPC_GUID_AFLPID; static const wchar16_t p_aflpid[6] = NT_IPC_OBJDIR_PREFIX_AFLPID; static int32_t __aflctl_get_service_attr( nt_rtdata * rtdata, nt_tty_service_info * aflctl) { nt_iosb iosb; /* inherited runtime data? */ if (rtdata->aflctl_keys[0]) { aflctl->attr.ver_major = 0; aflctl->attr.ver_minor = 0; aflctl->attr.options = 0; aflctl->attr.flags = 0; aflctl->attr.type = rtdata->aflctl_type; aflctl->attr.subtype = rtdata->aflctl_subtype; aflctl->attr.keys.key[0] = rtdata->aflctl_keys[0]; aflctl->attr.keys.key[1] = rtdata->aflctl_keys[1]; aflctl->attr.keys.key[2] = rtdata->aflctl_keys[2]; aflctl->attr.keys.key[3] = rtdata->aflctl_keys[3]; aflctl->attr.keys.key[4] = rtdata->aflctl_keys[4]; aflctl->attr.keys.key[5] = rtdata->aflctl_keys[5]; __ntapi->tt_guid_copy( &aflctl->attr.guid, &rtdata->aflctl_guid); return NT_STATUS_SUCCESS; } /* obtain service info */ return __ntapi->tty_query_information_service( 0,&iosb,aflctl, &(nt_guid)NT_PORT_GUID_AFLCTL, 0,0); } static int32_t __aflctl_server_connect( nt_rtdata * rtdata, nt_tty_service_info * aflctl) { int32_t status; /* already cononected? */ if (rtdata->haflctl) return NT_STATUS_SUCCESS; /* connect */ if ((status = __ntapi->ipc_connect_by_attr( &rtdata->haflctl, &aflctl->attr))) return status; /* update */ rtdata->aflctl_type = aflctl->attr.type; rtdata->aflctl_subtype = aflctl->attr.subtype; rtdata->aflctl_keys[0] = aflctl->attr.keys.key[0]; rtdata->aflctl_keys[1] = aflctl->attr.keys.key[1]; rtdata->aflctl_keys[2] = aflctl->attr.keys.key[2]; rtdata->aflctl_keys[3] = aflctl->attr.keys.key[3]; rtdata->aflctl_keys[4] = aflctl->attr.keys.key[4]; rtdata->aflctl_keys[5] = aflctl->attr.keys.key[5]; __ntapi->tt_guid_copy( &rtdata->aflctl_guid, &aflctl->attr.guid); return NT_STATUS_SUCCESS; } static int32_t __aflpid_symlink_set( nt_rtdata * rtdata, nt_tty_service_info * aflctl) { int32_t status; void * hpiddir; nt_port_name svcname; nt_unicode_string str; if (rtdata->haflpid) return NT_STATUS_SUCCESS; if (!rtdata->haflpiddir) { 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_aflpid,&g_aflpid))) return status; if (at_locked_cas((intptr_t *)&rtdata->haflpiddir,0,(intptr_t)hpiddir)) __ntapi->zw_close(hpiddir); } __ntapi->tt_port_name_from_attr( &svcname,&aflctl->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->haflpid, NT_SEC_STANDARD_RIGHTS_ALL, rtdata->haflpiddir, 0,&str, pe_get_current_process_id()); } static int32_t __stdcall __afl_open( void * hipc, nt_afl_info * afl, nt_iosb * iosb, nt_guid * afldev, uint32_t opcode) { int32_t status; nt_tty_port_msg msg; nt_iosb siosb; nt_tty_service_info aflctl; nt_runtime_data * rtdata; /* init */ rtdata = (__ntapi_internals())->rtdata; /* aflctl service attributes */ if (!rtdata->haflpid) if ((status = __aflctl_get_service_attr(rtdata,&aflctl))) return status; /* aflctl server */ if ((status = __aflctl_server_connect(rtdata,&aflctl))) return status; /* aflpid symlink */ if ((status = __aflpid_symlink_set(rtdata,&aflctl))) return status; /* hipc */ if (!hipc && (opcode == NT_TTY_AFL_ALLOC)) hipc = (__ntapi_internals())->rtdata->haflctl; /* obtain afl info */ __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_afl_info_msg) - sizeof(msg.header); msg.header.msg_size = sizeof(msg); msg.ttyinfo.opcode = opcode; __ntapi->tt_guid_copy( &msg.aflinfo.afldev, afldev); /* todo: device guid */ 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; /* new afl node? */ if (opcode == NT_TTY_AFL_ALLOC) if ((status = __ntapi->ipc_connect_by_attr( &hipc,&msg.svcinfo.attr))) return status; /* all done */ __ntapi->tt_aligned_block_memset( (uintptr_t *)afl, 0,sizeof(*afl)); afl->hport = hipc; __ntapi->tt_guid_copy( &afl->afldev, afldev); return NT_STATUS_SUCCESS; } int32_t __stdcall __ntapi_afl_create( __in void * hport, __out nt_afl_info * afl, __in nt_oa * oa, __out nt_iosb * iosb) { nt_guid afldev; /* validate */ if (!oa->root_dir) return NT_STATUS_DIRECTORY_SERVICE_REQUIRED; if (!oa->obj_name) return NT_STATUS_INVALID_PARAMETER; if (oa->obj_name->strlen != sizeof(nt_guid_str_utf16)) return NT_STATUS_OBJECT_NAME_INVALID; if (__ntapi->tt_string_to_guid_utf16( (nt_guid_str_utf16 *)oa->obj_name->buffer, &afldev)) return NT_STATUS_OBJECT_NAME_INVALID; /* open afldev */ return __afl_open( hport,afl,iosb, &afldev, NT_TTY_AFL_ALLOC); } int32_t __stdcall __ntapi_afl_open( __in void * hport, __out nt_afl_info * afl, __in nt_oa * oa, __out nt_iosb * iosb) { int32_t status; nt_guid afldev; void * hsymlink; nt_oa ipcoa; void * hipc; nt_rtdata * rtdata; nt_tty_service_info aflctl; /* init */ rtdata = (__ntapi_internals())->rtdata; /* validate */ if (!oa->root_dir) return NT_STATUS_DIRECTORY_SERVICE_REQUIRED; if (!oa->obj_name) return NT_STATUS_INVALID_PARAMETER; if (oa->obj_name->strlen != sizeof(nt_guid_str_utf16)) return NT_STATUS_OBJECT_NAME_INVALID; if (__ntapi->tt_string_to_guid_utf16( (nt_guid_str_utf16 *)oa->obj_name->buffer, &afldev)) return NT_STATUS_OBJECT_NAME_INVALID; /* open symlink */ 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 __afl_open( hport,afl,iosb, &afldev, NT_TTY_AFL_ALLOC); else return status; default: return status; } /* aflctl service attributes */ if (!rtdata->haflpid) if ((status = __aflctl_get_service_attr(rtdata,&aflctl))) return status; /* aflctl server */ if ((status = __aflctl_server_connect(rtdata,&aflctl))) return status; /* aflpid symlink */ if ((status = __aflpid_symlink_set(rtdata,&aflctl))) return status; /* ipc connect */ status = __ntapi->ipc_connect_by_symlink( &hipc,hsymlink); __ntapi->zw_close( hsymlink); if (status) return status; return __afl_open( hipc,afl,iosb, &afldev, NT_TTY_AFL_OPEN); }