Blame src/internal/toksvc_log_impl.c

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