/*********************************************************/
/* toksvc: a framework-native token broker service */
/* Copyright (C) 2020 SysDeer Technologies, LLC */
/* Released under GPLv2 and GPLv3; see COPYING.TOKSVC. */
/*********************************************************/
#include <psxtypes/psxtypes.h>
#include "toksvc_driver_impl.h"
#include "toksvc_dprintf_impl.h"
#include "toksvc_log_impl.h"
static const char * toks_log_entry_header[15] = {
[TOKS_LOG_ENTRY_SERVER_STATUS] = "SERVER (STATUS):",
[TOKS_LOG_ENTRY_SERVER_INFO] = "SERVER (INFO): ",
[TOKS_LOG_ENTRY_SERVER_ERROR] = "SERVER (ERROR): ",
[TOKS_LOG_ENTRY_CLIENT_STATUS] = "CLIENT (STATUS):",
[TOKS_LOG_ENTRY_CLIENT_INFO] = "CLIENT (INFO): ",
[TOKS_LOG_ENTRY_CLIENT_ERROR] = "CLIENT (ERROR): ",
[TOKS_LOG_ENTRY_SUB_LEVEL_1] = " ├─",
[TOKS_LOG_ENTRY_SUB_LEVEL_2] = " ├───",
[TOKS_LOG_ENTRY_SUB_LEVEL_3] = " ├─────",
[TOKS_LOG_ENTRY_SUB_LEVEL_4] = " ├───────",
[TOKS_LOG_ENTRY_SUB_LEVEL_5] = " ├─────────",
[TOKS_LOG_ENTRY_SUB_LEVEL_6] = " ├───────────",
};
static int32_t toks_log_strconv_utf16_to_utf8(
const wchar16_t * wch,
size_t len,
char * ch,
size_t bufsize)
{
int32_t status;
nt_strconv_nativetomb params;
params.src = wch;
params.src_size_in_bytes = len;
params.dst = (unsigned char *)ch;
params.dst_size_in_bytes = bufsize;
params.code_points = 0;
params.bytes_written = 0;
status = ntapi->uc_convert_unicode_stream_utf16_to_utf8(¶ms);
if (status == NT_STATUS_SUCCESS)
ch[params.bytes_written] = 0;
return params.leftover_count
? NT_STATUS_ILLEGAL_CHARACTER
: status;
}
static int32_t toks_log_write_impl(
const struct toks_driver_ctx * dctx,
const void * buf,
size_t size)
{
int32_t status;
nt_runtime_data * rtdata;
ntapi_zw_write_file * iofn;
void * hlog;
void * hio;
void * hevent;
int fdtype;
nt_iosb iosb;
const char * ch;
/* size */
if (size >= 0x80000000)
return NT_STATUS_INVALID_PARAMETER;
/* rtdata, hevent, hlog */
hevent = toks_get_driver_hevent(dctx);
rtdata = toks_get_driver_rtdata(dctx);
hlog = rtdata->hlog;
ch = buf;
/* hio, io type */
if (hlog) {
hio = hlog;
fdtype = NT_FILE_TYPE_UNKNOWN;
} else {
hio = rtdata->hstderr;
fdtype = rtdata->stderr_type;
}
if (!hio)
return NT_STATUS_INVALID_HANDLE;
/* iofn */
iofn = (fdtype == NT_FILE_TYPE_PTY)
? (ntapi_zw_write_file *)toks_ntapi->pty_write
: toks_ntapi->zw_write_file;
/* iowrite */
do {
iosb.status = NT_STATUS_PENDING;
status = iofn(
hio,hevent,
0,0,&iosb,
(void *)ch,
size,0,0);
if (status == NT_STATUS_PENDING)
toks_ntapi->zw_wait_for_single_object(
hevent,0,0);
size -= iosb.info;
ch += iosb.info;
} while (size && (iosb.status == NT_STATUS_SUCCESS));
/* ret */
return iosb.status;
}
void toks_log_header(
const struct toks_driver_ctx * dctx,
enum toks_log_entry_type type,
const char * fmt,
...)
{
nt_filetime pcnt;
va_list ap;
char * ch;
char buf[2048];
toks_query_performance_counters(dctx,&pcnt);
va_start(ap, fmt);
ch = buf;
ch += ntapi->sprintf(ch,"\n[%08x.%08x]: ",pcnt.ihigh,pcnt.ulow);
ch += ntapi->sprintf(ch,"%s ",toks_log_entry_header[type]);
ch += ntapi->vsnprintf(ch, &buf[sizeof(buf)] - ch, fmt, ap);
va_end(ap);
toks_log_write_impl(dctx,buf,ch-buf);
}
void toks_log_write(
const struct toks_driver_ctx * dctx,
enum toks_log_entry_type type,
const char * fmt,
...)
{
va_list ap;
char * ch;
char buf[2048];
va_start(ap, fmt);
ch = buf;
ch += ntapi->sprintf(buf,"%s ",toks_log_entry_header[type]);
ch += ntapi->vsnprintf(ch, &buf[sizeof(buf)] - ch, fmt, ap);
va_end(ap);
toks_log_write_impl(dctx,buf,ch-buf);
}
void toks_log_get_process_name(void * hprocess, char * utf8, size_t bytes)
{
wchar16_t buf[0x1000];
nt_unicode_string * path;
path = (nt_unicode_string *)buf;
if (!(ntapi->zw_query_information_process(
hprocess,
NT_PROCESS_IMAGE_FILE_NAME,
buf,sizeof(buf),
&(uint32_t){0})))
if (!(toks_log_strconv_utf16_to_utf8(
path->buffer,
path->strlen,
utf8,bytes)))
return;
ntapi->tt_generic_memcpy(
utf8,
(char[]){'#','E','R','R','O','R',0},
7);
}
void toks_log_get_arbitrary_process_name(nt_cid * cid, char * utf8, size_t bytes)
{
void * hprocess = NT_INVALID_HANDLE_VALUE;
nt_oa oa = {sizeof(oa),0,0,0,0,0};
if (cid->process_id == 0) {
*utf8++ = '(';
*utf8++ = 'N';
*utf8++ = '/';
*utf8++ = 'A';
*utf8++ = ')';
*utf8++ = 0;
return;
}
ntapi->zw_open_process(
&hprocess,
NT_PROCESS_SYNCHRONIZE | NT_PROCESS_QUERY_INFORMATION,
&oa,cid);
if (hprocess == NT_INVALID_HANDLE_VALUE) {
ntapi->tt_generic_memcpy(
utf8,
(char[]){'#','E','R','R','O','R',0},
7);
return;
}
toks_log_get_process_name(
hprocess,
utf8,bytes);
ntapi->zw_close(
hprocess);
}
const char * toks_log_basename(const char * path)
{
const char * ch;
for (ch=path; *ch; ch++)
(void)0;
for (--ch; ch>=path; ch--)
if (*ch == '\\')
return ++ch;
return path;
}