| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| static void toks_daemon_token_release(struct toks_token * token) |
| { |
| void * hport; |
| struct _nt_tty_sync_msg msg; |
| uint32_t * keys; |
| |
| hport = token->client.hdaemon; |
| keys = token->keys.key; |
| |
| 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 = TOKS_DAEMON_RELEASE; |
| |
| msg.data.syncinfo.ipckeys[0] = keys[0]; |
| msg.data.syncinfo.ipckeys[1] = keys[1]; |
| msg.data.syncinfo.ipckeys[2] = keys[2]; |
| msg.data.syncinfo.ipckeys[3] = keys[3]; |
| msg.data.syncinfo.ipckeys[4] = keys[4]; |
| msg.data.syncinfo.ipckeys[5] = keys[5]; |
| |
| ntapi->zw_request_wait_reply_port( |
| hport,&msg,&msg); |
| } |
| |
| static int32_t toks_daemon_client_wait(void * rapunzel) |
| { |
| |
| int32_t status; |
| nt_ebi syncebi; |
| struct toks_token * token; |
| struct toks_client_ctx * client; |
| void * hduo[2]; |
| |
| token = (struct toks_token *)rapunzel; |
| client = &token->client; |
| |
| ntapi->zw_set_event(client->hswap,0); |
| |
| hduo[0] = client->hprocess; |
| hduo[1] = client->halert; |
| |
| ntapi->zw_wait_for_multiple_objects( |
| 2,hduo, |
| NT_WAIT_ANY, |
| NT_SYNC_NON_ALERTABLE, |
| 0); |
| |
| status = ntapi->zw_query_event( |
| client->halert, |
| NT_EVENT_BASIC_INFORMATION, |
| &syncebi,sizeof(syncebi), |
| &(size_t){0}); |
| |
| if ((status == NT_STATUS_SUCCESS) && !syncebi.signal_state) |
| toks_daemon_token_release(token); |
| |
| ntapi->zw_close(client->hprocess); |
| ntapi->zw_close(client->halert); |
| |
| return ntapi->zw_terminate_thread( |
| NT_CURRENT_THREAD_HANDLE, |
| NT_STATUS_SUCCESS); |
| } |
| |
| static void toks_daemon_token_reset(struct toks_token * token) |
| { |
| token->self = 0; |
| token->keys.key[0] = 0; |
| token->keys.key[1] = 0; |
| token->keys.key[2] = 0; |
| token->keys.key[3] = 0; |
| token->keys.key[4] = 0; |
| token->keys.key[5] = 0; |
| } |
| |
| static int32_t toks_daemon_token_instance( |
| struct toks_token * token, |
| struct toks_client_ctx * client) |
| { |
| int32_t status; |
| nt_thread_params params; |
| |
| if ((status = ntapi->tt_create_private_event( |
| &client->hswap, |
| NT_NOTIFICATION_EVENT, |
| NT_EVENT_NOT_SIGNALED))) |
| return status; |
| |
| status = ntapi->tt_create_private_event( |
| &client->halert, |
| NT_NOTIFICATION_EVENT, |
| NT_EVENT_NOT_SIGNALED); |
| |
| if (status) { |
| ntapi->zw_close(client->hswap); |
| return status; |
| } |
| |
| token->self = token; |
| token->client.hprocess = client->hprocess; |
| token->client.hswap = client->hswap; |
| token->client.halert = client->halert; |
| token->client.hdaemon = client->hdaemon; |
| token->client.cid.process_id = client->cid.process_id; |
| token->client.cid.thread_id = client->cid.thread_id; |
| token->client.tokpid = client->tokpid; |
| |
| ntapi->tt_aligned_block_memset( |
| ¶ms,0,sizeof(params)); |
| |
| params.hprocess = NT_CURRENT_PROCESS_HANDLE; |
| params.start = toks_daemon_client_wait; |
| params.ext_ctx = token; |
| params.ext_ctx_size = sizeof(*token); |
| params.stack_size_commit = 4 * 1024; |
| params.stack_size_reserve = 4 * 1024; |
| params.creation_flags = NT_CREATE_LOCAL_THREAD; |
| |
| if ((status = ntapi->tt_create_thread(¶ms))) { |
| toks_daemon_token_reset(token); |
| ntapi->zw_close(client->hswap); |
| ntapi->zw_close(client->halert); |
| return status; |
| } |
| |
| status = ntapi->zw_wait_for_single_object( |
| client->hswap, |
| NT_SYNC_NON_ALERTABLE, |
| 0); |
| |
| ntapi->zw_close(client->hswap); |
| |
| if (status) { |
| toks_daemon_token_reset(token); |
| ntapi->zw_close(client->halert); |
| return status; |
| } |
| |
| token->client.hinstance = params.hthread; |
| |
| return NT_STATUS_SUCCESS; |
| } |
| |
| static int32_t toks_daemon_queue(struct toks_daemon_ctx * dctx, const struct toks_client_ctx * client) |
| { |
| int nwaiters; |
| struct toks_waiter * waiter; |
| nt_tty_port_msg * msg; |
| void * hevent; |
| int32_t status; |
| |
| msg = &dctx->reply; |
| nwaiters = toks_get_driver_nwaiters(dctx->driver_ctx); |
| |
| if (nwaiters == TOKS_MAX_WAITERS) |
| return NT_STATUS_TIMEOUT; |
| |
| |
| status = ntapi->zw_duplicate_object( |
| client->hcaller, |
| msg->syncinfo.hevent, |
| NT_CURRENT_PROCESS_HANDLE, |
| &hevent, |
| NT_EVENT_QUERY_STATE|NT_EVENT_MODIFY_STATE, |
| 0,0); |
| |
| if (status) { |
| ntapi->zw_close(client->hprocess); |
| return status; |
| } |
| |
| if ((status = ntapi->zw_reset_event(hevent,&(int){0}))) { |
| ntapi->zw_close(client->hprocess); |
| ntapi->zw_close(hevent); |
| return status; |
| } |
| |
| |
| waiter = dctx->waiter_next; |
| |
| waiter->client.hprocess = client->hprocess; |
| waiter->client.hcaller = client->hcaller; |
| waiter->client.hevent = hevent; |
| |
| waiter->client.tokpid = client->tokpid; |
| waiter->client.cid.process_id = client->cid.process_id; |
| |
| toks_set_driver_nwaiters( |
| dctx->driver_ctx, |
| ++nwaiters); |
| |
| dctx->waiter_next++; |
| |
| if (dctx->waiter_next == dctx->waiter_cap) |
| dctx->waiter_next = dctx->waiter_base; |
| |
| ntapi->tt_generic_memcpy( |
| &waiter->msg,msg, |
| sizeof(*msg)); |
| |
| return NT_STATUS_PENDING; |
| } |
| |
| int32_t __stdcall toks_daemon_acquire(struct toks_daemon_ctx * dctx) |
| { |
| int32_t status; |
| nt_tty_port_msg * msg; |
| struct toks_client_ctx client; |
| nt_oa oa; |
| struct toks_token * token; |
| struct toks_token * tocap; |
| |
| msg = &dctx->reply; |
| |
| client.hport = 0; |
| client.hprocess = 0; |
| client.hcaller = 0; |
| client.hswap = 0; |
| client.hdaemon = dctx->hport_internal_client; |
| client.cid.process_id = msg->header.client_id.process_id; |
| client.cid.thread_id = 0; |
| client.tokpid = 0; |
| |
| oa.len = sizeof(oa); |
| oa.root_dir = 0; |
| oa.obj_name = 0; |
| oa.obj_attr = 0; |
| oa.sec_desc = 0; |
| oa.sec_qos = 0; |
| |
| if (dctx->opcode == TOKS_DAEMON_ACQUIRE) { |
| if ((dctx->reqtokpid = msg->syncinfo.ipcsvc.keys.reserved)) { |
| if (msg->syncinfo.ipcsvc.options & TOKS_OPT_FRAMEWORK_PID) { |
| if ((status = toks_daemon_pidopen(dctx))) |
| return status; |
| } else { |
| dctx->reqsyspid = dctx->reqtokpid; |
| } |
| |
| client.tokpid = dctx->reqtokpid; |
| client.cid.process_id = dctx->reqsyspid; |
| } |
| |
| if ((status = ntapi->zw_open_process( |
| &client.hprocess, |
| NT_PROCESS_SYNCHRONIZE |
| | NT_PROCESS_QUERY_INFORMATION, |
| &oa,&client.cid))) |
| return status; |
| } |
| |
| if ((dctx->ftokens == 0) && !msg->syncinfo.hevent) { |
| ntapi->zw_close(client.hprocess); |
| return NT_STATUS_TIMEOUT; |
| } |
| |
| toks_query_performance_counters(dctx->driver_ctx,&dctx->pcnt); |
| |
| if (dctx->ftokens == 0) { |
| status = ntapi->zw_open_process( |
| &client.hcaller, |
| NT_PROCESS_SYNCHRONIZE |
| | NT_PROCESS_DUP_HANDLE |
| | NT_PROCESS_QUERY_INFORMATION, |
| &oa,&msg->header.client_id); |
| |
| if (status) { |
| ntapi->zw_close(client.hprocess); |
| return status; |
| } |
| |
| msg->syncinfo.ipckeys[0] = ntapi->tt_buffer_crc32( |
| msg->header.msg_id, |
| &dctx->pcnt,sizeof(dctx->pcnt)); |
| |
| msg->syncinfo.ipckeys[1] = ntapi->tt_buffer_crc32( |
| msg->header.msg_id, |
| &msg->header,sizeof(msg->header)); |
| |
| msg->syncinfo.ipckeys[2] = ntapi->tt_buffer_crc32( |
| msg->header.msg_id, |
| &msg->syncinfo,sizeof(msg->syncinfo)); |
| |
| msg->syncinfo.ipckeys[3] = ntapi->tt_buffer_crc32( |
| msg->header.msg_id, |
| &client,sizeof(client)); |
| |
| msg->syncinfo.ipckeys[4] = ntapi->tt_buffer_crc32( |
| msg->header.msg_id, |
| toks_get_driver_tokens(dctx->driver_ctx), |
| toks_get_driver_ntokens(dctx->driver_ctx) |
| * sizeof(struct toks_token)); |
| |
| msg->syncinfo.ipckeys[5] = ntapi->tt_buffer_crc32( |
| msg->header.msg_id, |
| dctx,sizeof(*dctx)); |
| |
| return toks_daemon_queue(dctx,&client); |
| } |
| |
| token = toks_get_driver_tokens(dctx->driver_ctx); |
| tocap = &token[toks_get_driver_atokens(dctx->driver_ctx)]; |
| |
| for (; token->self && (token<tocap); ) |
| token++; |
| |
| if (dctx->opcode == TOKS_DAEMON_RELEASE) { |
| client.hprocess = msg->ttyinfo.exarg; |
| |
| token->keys.key[0] = msg->syncinfo.ipckeys[0]; |
| token->keys.key[1] = msg->syncinfo.ipckeys[1]; |
| token->keys.key[2] = msg->syncinfo.ipckeys[2]; |
| token->keys.key[3] = msg->syncinfo.ipckeys[3]; |
| token->keys.key[4] = msg->syncinfo.ipckeys[4]; |
| token->keys.key[5] = msg->syncinfo.ipckeys[5]; |
| } else { |
| token->keys.key[0] = ntapi->tt_buffer_crc32( |
| msg->header.msg_id, |
| &dctx->pcnt,sizeof(dctx->pcnt)); |
| |
| token->keys.key[1] = ntapi->tt_buffer_crc32( |
| msg->header.msg_id, |
| &msg->header,sizeof(msg->header)); |
| |
| token->keys.key[2] = ntapi->tt_buffer_crc32( |
| msg->header.msg_id, |
| &msg->syncinfo,sizeof(msg->syncinfo)); |
| |
| token->keys.key[3] = ntapi->tt_buffer_crc32( |
| msg->header.msg_id, |
| &client,sizeof(client)); |
| |
| token->keys.key[4] = ntapi->tt_buffer_crc32( |
| msg->header.msg_id, |
| toks_get_driver_tokens(dctx->driver_ctx), |
| toks_get_driver_ntokens(dctx->driver_ctx) |
| * sizeof(struct toks_token)); |
| |
| token->keys.key[5] = ntapi->tt_buffer_crc32( |
| msg->header.msg_id, |
| &token->keys,sizeof(token->keys)); |
| |
| msg->syncinfo.ipckeys[0] = token->keys.key[0]; |
| msg->syncinfo.ipckeys[1] = token->keys.key[1]; |
| msg->syncinfo.ipckeys[2] = token->keys.key[2]; |
| msg->syncinfo.ipckeys[3] = token->keys.key[3]; |
| msg->syncinfo.ipckeys[4] = token->keys.key[4]; |
| msg->syncinfo.ipckeys[5] = token->keys.key[5]; |
| } |
| |
| if ((token->meta.key[0] = msg->syncinfo.ipcsvc.keys.key[0])) { |
| token->meta.key[1] = msg->syncinfo.ipcsvc.keys.key[1]; |
| token->meta.key[2] = msg->syncinfo.ipcsvc.keys.key[2]; |
| token->meta.key[3] = msg->syncinfo.ipcsvc.keys.key[3]; |
| token->meta.key[4] = msg->syncinfo.ipcsvc.keys.key[4]; |
| token->meta.key[5] = msg->syncinfo.ipcsvc.keys.key[5]; |
| } |
| |
| if ((status = toks_daemon_token_instance(token,&client))) { |
| toks_daemon_token_reset(token); |
| ntapi->zw_close(client.hprocess); |
| return status; |
| } |
| |
| dctx->utokens++; |
| dctx->ftokens--; |
| |
| return NT_STATUS_SUCCESS; |
| } |