-
-
Notifications
You must be signed in to change notification settings - Fork 559
/
dll_log.cpp
112 lines (91 loc) · 3.18 KB
/
dll_log.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
/*
* Copyright (C) 2014 Patrick Mours
* SPDX-License-Identifier: BSD-3-Clause OR MIT
*/
#include "dll_log.hpp"
#include <Windows.h>
struct scoped_file_handle
{
~scoped_file_handle()
{
if (handle != INVALID_HANDLE_VALUE)
CloseHandle(handle);
}
operator HANDLE() const { return handle; }
void operator=(HANDLE new_handle)
{
handle = new_handle;
}
private:
HANDLE handle = INVALID_HANDLE_VALUE;
};
static scoped_file_handle s_file_handle;
bool reshade::log::open_log_file(const std::filesystem::path &path, std::error_code &ec)
{
// Close the previous file first
// Do this here, instead of in 'scoped_file_handle::operator=', so that the old handle is closed before the new handle is created
if (s_file_handle != INVALID_HANDLE_VALUE)
CloseHandle(s_file_handle);
// Open the log file for writing (and flush on each write) and clear previous contents
s_file_handle = CreateFileW(path.c_str(), GENERIC_WRITE, FILE_SHARE_READ, nullptr, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_WRITE_THROUGH, NULL);
if (s_file_handle != INVALID_HANDLE_VALUE)
{
// Last error may be ERROR_ALREADY_EXISTS if an existing file was overwritten, which can be ignored
ec.clear();
return true;
}
else
{
ec.assign(GetLastError(), std::system_category());
return false;
}
}
void reshade::log::message(level level, const char *format, ...)
{
static constexpr char level_names[][6] = { "ERROR", "WARN ", "INFO ", "DEBUG" };
if (static_cast<size_t>(level) == 0)
level = level::error;
if (static_cast<size_t>(level) > std::size(level_names))
level = level::debug;
SYSTEMTIME time;
GetLocalTime(&time);
std::string line_string;
line_string.resize(256);
// Start a new line
const auto meta_length = std::snprintf(line_string.data(), line_string.size(),
#if RESHADE_VERBOSE_LOG
"%04hd-%02hd-%02hdT"
#endif
"%02hd:%02hd:%02hd:%03hd [%5lu] | %.5s | ",
#if RESHADE_VERBOSE_LOG
time.wYear, time.wMonth, time.wDay,
#endif
time.wHour, time.wMinute, time.wSecond, time.wMilliseconds, GetCurrentThreadId(), level_names[static_cast<size_t>(level) - 1]);
va_list args;
va_start(args, format);
const auto content_length = std::vsnprintf(line_string.data() + meta_length, line_string.size() + 1 - meta_length, format, args);
va_end(args);
const auto remaining_content = static_cast<size_t>(meta_length) + static_cast<size_t>(content_length) > line_string.size();
line_string.resize(static_cast<size_t>(meta_length) + static_cast<size_t>(content_length));
if (remaining_content)
{
va_start(args, format);
std::vsnprintf(line_string.data() + meta_length, line_string.size() + 1 - meta_length, format, args);
va_end(args);
}
line_string += '\n'; // Terminate line with line feed
// Replace all LF with CRLF
for (size_t offset = 0; (offset = line_string.find('\n', offset)) != std::string::npos; offset += 2)
line_string.replace(offset, 1, "\r\n", 2);
// Write line to the log file
if (s_file_handle != INVALID_HANDLE_VALUE)
{
DWORD written = 0;
WriteFile(s_file_handle, line_string.data(), static_cast<DWORD>(line_string.size()), &written, nullptr);
assert(written == line_string.size());
}
#ifndef NDEBUG
// Write line to the debug output
OutputDebugStringA(line_string.c_str());
#endif
}