mirror of
https://github.com/reactos/reactos.git
synced 2024-11-10 16:48:16 +00:00
a7fddf9c07
svn path=/trunk/; revision=29689
160 lines
4.2 KiB
C
160 lines
4.2 KiB
C
/* Written by Krzysztof Kowalczyk (http://blog.kowalczyk.info)
|
|
The author disclaims copyright to this source code. */
|
|
#include "log_util.h"
|
|
#include "str_util.h"
|
|
|
|
/* Simple logging. 'slog' stands for "simple logging". I figured that 'log'
|
|
is a very common name so used something else, but still short as a prefix
|
|
for API names */
|
|
|
|
/* TODO: slogfmt(const char *fmt, ...) */
|
|
|
|
/* TODO: extend to more than one file, by keeping a list of file names */
|
|
const TCHAR * g_cur_fileName = NULL;
|
|
|
|
/* initialize logging system, should be called before any logging calls */
|
|
BOOL slog_init(void)
|
|
{
|
|
/* do nothing yet */
|
|
return TRUE;
|
|
}
|
|
|
|
/* deinitialize logging system. Should be called before the program quits */
|
|
void slog_deinit(void)
|
|
{
|
|
slog_file_log_stop(NULL);
|
|
}
|
|
|
|
/* start logging to a file 'fileName'. From now on until slog_file_log_stop()
|
|
all slog* logging will also go to a file. If a file of that name already
|
|
exists, it'll overwrite it. */
|
|
BOOL slog_file_log_start(const TCHAR *fileName)
|
|
{
|
|
if (!fileName) return FALSE;
|
|
g_cur_fileName = tstr_dup(fileName);
|
|
DeleteFile(fileName);
|
|
return TRUE;
|
|
}
|
|
|
|
/* like 'slog_file_log_start' but will create a unique file based on 'fileName'.
|
|
If a 'fileName' has extension, it'll try the first available
|
|
'$file-$NNN.$ext' file (e.g. "my-app-log-000.txt") if 'fileName' is "my-app-log.txt"
|
|
If there is no extension, it'll be '$file-$NNN' */
|
|
int slog_file_log_unique_start(const TCHAR *fileName)
|
|
{
|
|
assert(0); /* not implemented */
|
|
return FALSE;
|
|
}
|
|
|
|
void slog_file_log_stop(const TCHAR *fileName)
|
|
{
|
|
/* 'fileName' is currently unused. The idea is that it should match the
|
|
name given to slog_file_log_start */
|
|
if (g_cur_fileName) {
|
|
free((void*)g_cur_fileName);
|
|
g_cur_fileName = NULL;
|
|
}
|
|
}
|
|
|
|
/* log 'txt' to all currently enabled loggers */
|
|
void slog_str(const char *txt)
|
|
{
|
|
DWORD to_write_cb;
|
|
DWORD written_cb;
|
|
int f_ok;
|
|
HANDLE fh;
|
|
|
|
if (!txt) return;
|
|
|
|
if (!g_cur_fileName) return;
|
|
|
|
/* we're using this inefficient way of re-opening the file for each
|
|
log so that we can also watch this file life using tail-like program */
|
|
fh = CreateFile(g_cur_fileName, GENERIC_WRITE, FILE_SHARE_READ, NULL,
|
|
OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
|
|
if (INVALID_HANDLE_VALUE == fh)
|
|
return;
|
|
SetFilePointer(fh, 0, NULL, FILE_END);
|
|
to_write_cb = (DWORD)strlen(txt);
|
|
f_ok = WriteFile(fh, (void*)txt, to_write_cb, &written_cb, NULL);
|
|
assert(f_ok && (written_cb == to_write_cb));
|
|
CloseHandle(fh);
|
|
}
|
|
|
|
void slog_str_printf(const char *format, ...)
|
|
{
|
|
char * tmp;
|
|
va_list args;
|
|
|
|
va_start(args, format);
|
|
tmp = str_printf_args(format, args);
|
|
va_end(args);
|
|
if (!tmp) return;
|
|
slog_str(tmp);
|
|
free(tmp);
|
|
}
|
|
|
|
static WCHAR* last_error_as_wstr(void)
|
|
{
|
|
WCHAR *msgBuf = NULL;
|
|
WCHAR *copy;
|
|
FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
|
|
NULL, GetLastError(), MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
|
|
(LPTSTR) &msgBuf, 0, NULL);
|
|
if (!msgBuf) return NULL;
|
|
copy = wstr_dup(msgBuf);
|
|
LocalFree(msgBuf);
|
|
return copy;
|
|
}
|
|
|
|
void slog_last_error(const char *optional_prefix)
|
|
{
|
|
WCHAR *txt = last_error_as_wstr();
|
|
if (!txt) return;
|
|
slog_str(optional_prefix);
|
|
slog_wstr_nl(txt);
|
|
free(txt);
|
|
}
|
|
|
|
/* TODO: converting by casting isn't always correct but here we don't care much */
|
|
char *wstr_to_str(const WCHAR *txt)
|
|
{
|
|
char *txt_copy, *tmp;
|
|
|
|
if (!txt) return NULL;
|
|
|
|
txt_copy = (char*)malloc(tstr_len(txt) + 1);
|
|
if (!txt_copy) return NULL;
|
|
|
|
tmp = txt_copy;
|
|
while (*txt) {
|
|
*tmp++ = (char)*txt++;
|
|
}
|
|
*tmp = 0;
|
|
return txt_copy;
|
|
}
|
|
|
|
void slog_wstr(const WCHAR *txt)
|
|
{
|
|
char *txt_copy;
|
|
|
|
txt_copy = wstr_to_str(txt);
|
|
if (!txt_copy) return;
|
|
slog_str(txt_copy);
|
|
free(txt_copy);
|
|
}
|
|
|
|
/* log 'txt' to all currently enabled loggers and add newline */
|
|
void slog_str_nl(const char *txt)
|
|
{
|
|
/* TODO: given the 'reopen the file each time' implementation of
|
|
slgotxt, this should be optimized */
|
|
slog_str(txt);
|
|
slog_str("\n");
|
|
}
|
|
|
|
void slog_wstr_nl(const WCHAR *txt)
|
|
{
|
|
slog_wstr(txt);
|
|
slog_wstr(_T("\n"));
|
|
}
|