| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| static int32_t toks_daemon_ioctl_get_token_count(struct toks_daemon_ctx * dctx) |
| { |
| nt_tty_port_msg * msg = &dctx->reply; |
| msg->ttyinfo.exarg = (void *)(intptr_t)toks_get_driver_ntokens(dctx->driver_ctx); |
| return NT_STATUS_SUCCESS; |
| } |
| |
| static int32_t toks_daemon_ioctl_set_token_count(struct toks_daemon_ctx * dctx) |
| { |
| nt_tty_port_msg * msg; |
| int ntokens; |
| |
| msg = &dctx->reply; |
| ntokens = (int)(intptr_t)msg->ttyinfo.exarg; |
| |
| if (ntokens < 0) |
| return NT_STATUS_INVALID_PARAMETER; |
| |
| else if (ntokens > toks_get_driver_atokens(dctx->driver_ctx)) |
| return NT_STATUS_BUFFER_TOO_SMALL; |
| |
| toks_set_driver_ntokens(dctx->driver_ctx,ntokens); |
| |
| dctx->ftokens = (dctx->utokens < ntokens) |
| ? ntokens - dctx->utokens : 0; |
| |
| return toks_daemon_release(dctx); |
| } |
| |
| static int32_t toks_daemon_ioctl_get_log_level(struct toks_daemon_ctx * dctx) |
| { |
| nt_tty_port_msg * msg = &dctx->reply; |
| msg->ttyinfo.exarg = (void *)(intptr_t)dctx->driver_ctx->cctx->loglevel; |
| return NT_STATUS_SUCCESS; |
| } |
| |
| static int32_t toks_daemon_ioctl_set_log_level(struct toks_daemon_ctx * dctx) |
| { |
| nt_tty_port_msg * msg; |
| int loglevel; |
| |
| msg = &dctx->reply; |
| loglevel = (int)(intptr_t)msg->ttyinfo.exarg; |
| |
| if ((loglevel < 0) || (loglevel > 9)) |
| return NT_STATUS_INVALID_PARAMETER; |
| |
| toks_set_driver_log_level(dctx->driver_ctx,loglevel); |
| |
| toks_log_service_info(dctx); |
| |
| return NT_STATUS_SUCCESS; |
| } |
| |
| static int32_t toks_daemon_ioctl_get_service_info(struct toks_daemon_ctx * dctx) |
| { |
| nt_tty_port_msg * msg = &dctx->reply; |
| |
| |
| msg->svcdata.meta[0] = (dctx->driver_ctx->cctx->uuid->data1); |
| |
| msg->svcdata.meta[1] = (dctx->driver_ctx->cctx->uuid->data2); |
| msg->svcdata.meta[1] |= (dctx->driver_ctx->cctx->uuid->data3 << 16); |
| |
| msg->svcdata.meta[2] = (dctx->driver_ctx->cctx->uuid->data4[0]); |
| msg->svcdata.meta[2] |= (dctx->driver_ctx->cctx->uuid->data4[1] << 8); |
| msg->svcdata.meta[2] |= (dctx->driver_ctx->cctx->uuid->data4[2] << 16); |
| msg->svcdata.meta[2] |= (dctx->driver_ctx->cctx->uuid->data4[3] << 24); |
| |
| msg->svcdata.meta[3] = (dctx->driver_ctx->cctx->uuid->data4[4]); |
| msg->svcdata.meta[3] |= (dctx->driver_ctx->cctx->uuid->data4[5] << 8); |
| msg->svcdata.meta[3] |= (dctx->driver_ctx->cctx->uuid->data4[6] << 16); |
| msg->svcdata.meta[3] |= (dctx->driver_ctx->cctx->uuid->data4[7] << 24); |
| |
| |
| msg->svcdata.data[0] = pe_get_current_process_id(); |
| msg->svcdata.data[1] = pe_get_current_thread_id(); |
| |
| |
| msg->svcdata.data[2] = dctx->ctrlpid; |
| msg->svcdata.data[3] = dctx->csyspid; |
| |
| |
| msg->svcdata.data[4] = toks_get_driver_atokens(dctx->driver_ctx); |
| msg->svcdata.data[5] = toks_get_driver_ntokens(dctx->driver_ctx); |
| msg->svcdata.data[6] = toks_get_driver_nwaiters(dctx->driver_ctx); |
| |
| |
| msg->svcdata.data[7] = dctx->utokens; |
| msg->svcdata.data[8] = dctx->ftokens; |
| |
| return NT_STATUS_SUCCESS; |
| } |
| |
| static int32_t toks_daemon_ioctl_log_service_info(struct toks_daemon_ctx * dctx) |
| { |
| toks_log_service_info(dctx); |
| return NT_STATUS_SUCCESS; |
| } |
| |
| static int32_t toks_daemon_ioctl_get_token_info(struct toks_daemon_ctx * dctx) |
| { |
| int32_t status; |
| void * hprocess; |
| void * hfile; |
| void * hrfile; |
| void * addr; |
| char * mark; |
| size_t size; |
| int32_t idx; |
| nt_oa oa; |
| nt_sd_common_buffer sd; |
| nt_iosb iosb; |
| nt_unicode_string path; |
| nt_large_integer asize; |
| struct toks_token * token; |
| struct toks_waiter * waiter; |
| struct toks_token_ctx * tctx; |
| struct toks_token_info * tinfo; |
| struct toks_token_sctx stctx; |
| uint32_t access; |
| uint32_t access_owner; |
| uint32_t access_group; |
| uint32_t access_other; |
| uint32_t access_admin; |
| int32_t nwaiters; |
| uint32_t keys[4]; |
| wchar16_t name[37]; |
| |
| |
| toks_daemon_ioctl_get_service_info(dctx); |
| |
| |
| oa.len = sizeof(nt_oa); |
| oa.root_dir = 0; |
| oa.obj_name = 0; |
| oa.obj_attr = 0; |
| oa.sec_desc = 0; |
| oa.sec_qos = 0; |
| |
| if ((status = ntapi->zw_open_process( |
| &hprocess, |
| NT_PROCESS_SYNCHRONIZE |
| | NT_PROCESS_DUP_HANDLE |
| | NT_PROCESS_QUERY_INFORMATION, |
| &oa,&dctx->request.header.client_id))) |
| return status; |
| |
| |
| access_owner = NT_GENERIC_READ | NT_GENERIC_WRITE; |
| access_group = NT_SEC_READ_CONTROL | NT_FILE_READ_ATTRIBUTES; |
| access_other = NT_SEC_READ_CONTROL | NT_FILE_READ_ATTRIBUTES; |
| |
| access_owner |= NT_SEC_STANDARD_RIGHTS_ALL; |
| access_admin = access_owner; |
| |
| ntapi->acl_init_common_descriptor( |
| &sd,0,0,0,0, |
| access_owner,access_group,access_other, |
| access_admin,access_owner, |
| 0); |
| |
| |
| toks_query_performance_counters( |
| dctx->driver_ctx, |
| &dctx->pcnt); |
| |
| keys[0] = ntapi->tt_buffer_crc32( |
| dctx->noise, |
| &dctx->pcnt,sizeof(dctx->pcnt)); |
| |
| keys[1] = ntapi->tt_buffer_crc32( |
| keys[0], |
| &dctx->request.header,sizeof(dctx->request.header)); |
| |
| keys[2] = ntapi->tt_buffer_crc32( |
| keys[1], |
| toks_get_driver_tokens(dctx->driver_ctx), |
| toks_get_driver_ntokens(dctx->driver_ctx) |
| * sizeof(struct toks_token)); |
| |
| keys[3] = ntapi->tt_buffer_crc32( |
| keys[2], |
| dctx,sizeof(*dctx)); |
| |
| name[0] = '.'; |
| name[9] = '.'; |
| name[18] = '.'; |
| name[27] = '.'; |
| name[36] = 0; |
| |
| ntapi->tt_uint32_to_hex_utf16(keys[0],&name[1]); |
| ntapi->tt_uint32_to_hex_utf16(keys[1],&name[10]); |
| ntapi->tt_uint32_to_hex_utf16(keys[2],&name[19]); |
| ntapi->tt_uint32_to_hex_utf16(keys[3],&name[28]); |
| |
| |
| path.strlen = 36 * sizeof(wchar16_t); |
| path.maxlen = 0; |
| path.buffer = name; |
| |
| |
| oa.len = sizeof(nt_oa); |
| oa.root_dir = toks_get_driver_tmpfs(dctx->driver_ctx); |
| oa.obj_name = &path; |
| oa.obj_attr = 0; |
| oa.sec_desc = &sd.sd; |
| oa.sec_qos = 0; |
| |
| |
| access = NT_SEC_SYNCHRONIZE | NT_SEC_DELETE; |
| access |= NT_FILE_READ_DATA | NT_FILE_READ_ATTRIBUTES; |
| access |= NT_FILE_WRITE_DATA | NT_FILE_WRITE_ATTRIBUTES; |
| |
| |
| nwaiters = toks_get_driver_nwaiters(dctx->driver_ctx); |
| |
| asize.quad = __offsetof(struct toks_token_ctx,tokens); |
| asize.quad += sizeof(struct toks_token_info) * dctx->utokens; |
| asize.quad += sizeof(struct toks_token_info) * nwaiters; |
| |
| |
| status = ntapi->zw_create_file( |
| &hfile, |
| access,&oa,&iosb,&asize, |
| NT_FILE_ATTRIBUTE_NORMAL, |
| 0,NT_FILE_CREATE, |
| NT_FILE_NON_DIRECTORY_FILE |
| | NT_FILE_SYNCHRONOUS_IO_ALERT |
| | NT_FILE_DELETE_ON_CLOSE, |
| 0,0); |
| |
| if (status) { |
| ntapi->zw_close(hprocess); |
| return status; |
| } |
| |
| |
| if ((dctx->utokens + nwaiters) <= 512) { |
| tctx = 0; |
| addr = &stctx; |
| size = asize.quad; |
| tinfo = stctx.tokens; |
| |
| stctx.allocated = toks_get_driver_atokens(dctx->driver_ctx); |
| stctx.available = toks_get_driver_ntokens(dctx->driver_ctx); |
| stctx.pending = nwaiters; |
| stctx.tused = dctx->utokens; |
| stctx.tfree = dctx->ftokens; |
| } else { |
| size = asize.quad; |
| addr = toks_calloc(1,size); |
| |
| if (!addr) { |
| ntapi->zw_close(hfile); |
| ntapi->zw_close(hprocess); |
| return NT_STATUS_MEMORY_NOT_ALLOCATED; |
| } |
| |
| tctx = (struct toks_token_ctx *)addr; |
| tinfo = tctx->tokens; |
| |
| tctx->allocated = toks_get_driver_atokens(dctx->driver_ctx); |
| tctx->available = toks_get_driver_ntokens(dctx->driver_ctx); |
| tctx->pending = nwaiters; |
| tctx->tused = dctx->utokens; |
| tctx->tfree = dctx->ftokens; |
| } |
| |
| |
| token = toks_get_driver_tokens(dctx->driver_ctx); |
| |
| for (idx=0; idx<dctx->utokens; token++) { |
| if (token->self) { |
| tinfo->tokpid = token->client.tokpid; |
| tinfo->tsyspid = token->client.cid.process_id; |
| tinfo->pad = 0; |
| |
| tinfo->keys[0] = token->keys.key[0]; |
| tinfo->keys[1] = token->keys.key[1]; |
| tinfo->keys[2] = token->keys.key[2]; |
| tinfo->keys[3] = token->keys.key[3]; |
| tinfo->keys[4] = token->keys.key[4]; |
| tinfo->keys[5] = token->keys.key[5]; |
| |
| tinfo->meta[0] = token->meta.key[0]; |
| tinfo->meta[1] = token->meta.key[1]; |
| tinfo->meta[2] = token->meta.key[2]; |
| tinfo->meta[3] = token->meta.key[3]; |
| tinfo->meta[4] = token->meta.key[4]; |
| tinfo->meta[5] = token->meta.key[5]; |
| |
| idx++; |
| tinfo++; |
| } |
| } |
| |
| |
| idx = 0; |
| waiter = dctx->waiter_first; |
| |
| for (; idx<nwaiters; ) { |
| if (waiter->msg.header.msg_id) { |
| tinfo->tokpid = waiter->client.tokpid; |
| tinfo->tsyspid = waiter->client.cid.process_id; |
| tinfo->pad = 0; |
| |
| tinfo->keys[0] = waiter->msg.syncinfo.ipckeys[0]; |
| tinfo->keys[1] = waiter->msg.syncinfo.ipckeys[1]; |
| tinfo->keys[2] = waiter->msg.syncinfo.ipckeys[2]; |
| tinfo->keys[3] = waiter->msg.syncinfo.ipckeys[3]; |
| tinfo->keys[4] = waiter->msg.syncinfo.ipckeys[4]; |
| tinfo->keys[5] = waiter->msg.syncinfo.ipckeys[5]; |
| |
| tinfo->meta[0] = waiter->msg.syncinfo.ipcsvc.keys.key[0]; |
| tinfo->meta[1] = waiter->msg.syncinfo.ipcsvc.keys.key[1]; |
| tinfo->meta[2] = waiter->msg.syncinfo.ipcsvc.keys.key[2]; |
| tinfo->meta[3] = waiter->msg.syncinfo.ipcsvc.keys.key[3]; |
| tinfo->meta[4] = waiter->msg.syncinfo.ipcsvc.keys.key[4]; |
| tinfo->meta[5] = waiter->msg.syncinfo.ipcsvc.keys.key[5]; |
| |
| idx++; |
| tinfo++; |
| } |
| |
| if (++waiter == dctx->waiter_cap) |
| waiter = dctx->waiter_base; |
| } |
| |
| |
| for (mark=addr; size; size-=iosb.info) { |
| status = ntapi->zw_write_file( |
| hfile,0,0,0, |
| &iosb,addr,size, |
| 0,0); |
| |
| switch (status) { |
| case NT_STATUS_SUCCESS: |
| mark += iosb.info; |
| addr = mark; |
| break; |
| |
| default: |
| ntapi->zw_close(hfile); |
| ntapi->zw_close(hprocess); |
| |
| if (tctx) |
| toks_free(tctx); |
| |
| return status; |
| } |
| } |
| |
| |
| if (tctx) |
| toks_free(tctx); |
| |
| |
| status = ntapi->zw_duplicate_object( |
| NT_CURRENT_PROCESS_HANDLE, |
| hfile, |
| hprocess, |
| &hrfile, |
| 0,0, |
| NT_DUPLICATE_SAME_ACCESS |
| | NT_DUPLICATE_SAME_ATTRIBUTES); |
| |
| |
| ntapi->zw_close(hfile); |
| ntapi->zw_close(hprocess); |
| |
| switch (status) { |
| case NT_STATUS_SUCCESS: |
| dctx->reply.ttyinfo.exarg = hrfile; |
| return NT_STATUS_SUCCESS; |
| |
| default: |
| dctx->reply.ttyinfo.exarg = 0; |
| return status; |
| } |
| } |
| |
| static int32_t toks_daemon_ioctl_log_token_info(struct toks_daemon_ctx * dctx) |
| { |
| toks_log_token_info(dctx); |
| return NT_STATUS_SUCCESS; |
| } |
| |
| int32_t __stdcall toks_daemon_ioctl(struct toks_daemon_ctx * dctx) |
| { |
| nt_tty_port_msg * msg; |
| uint32_t ctlcode; |
| |
| msg = &dctx->reply; |
| ctlcode = msg->ttyinfo.opdata; |
| |
| switch (ctlcode) { |
| case TOKS_IOCTL_GET_TOKEN_COUNT: |
| return toks_daemon_ioctl_get_token_count(dctx); |
| |
| case TOKS_IOCTL_SET_TOKEN_COUNT: |
| return toks_daemon_ioctl_set_token_count(dctx); |
| |
| case TOKS_IOCTL_GET_SERVICE_INFO: |
| return toks_daemon_ioctl_get_service_info(dctx); |
| |
| case TOKS_IOCTL_LOG_SERVICE_INFO: |
| return toks_daemon_ioctl_log_service_info(dctx); |
| |
| case TOKS_IOCTL_GET_TOKEN_INFO: |
| return toks_daemon_ioctl_get_token_info(dctx); |
| |
| case TOKS_IOCTL_LOG_TOKEN_INFO: |
| return toks_daemon_ioctl_log_token_info(dctx); |
| |
| case TOKS_IOCTL_GET_LOG_LEVEL: |
| return toks_daemon_ioctl_get_log_level(dctx); |
| |
| case TOKS_IOCTL_SET_LOG_LEVEL: |
| return toks_daemon_ioctl_set_log_level(dctx); |
| |
| default: |
| return NT_STATUS_NOT_IMPLEMENTED; |
| } |
| } |