Skip to content

Commit efbeab2

Browse files
committed
api: upgrade logging
Log runtime information to quickly check whether the values are sane when analyzing error logs sent in by users. Signed-off-by: Simon Rozman <[email protected]>
1 parent 542a281 commit efbeab2

File tree

9 files changed

+422
-177
lines changed

9 files changed

+422
-177
lines changed

api/adapter.c

Lines changed: 177 additions & 112 deletions
Large diffs are not rendered by default.

api/elevate.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ _Return_type_success_(return != FALSE) BOOL ElevateToSystem(void)
4242
CloseHandle(CurrentProcessToken);
4343
if (!Ret)
4444
{
45-
LOG_ERROR(L"Failed to get token information", LastError);
45+
LOG_ERROR(LastError, L"Failed to get token information");
4646
goto cleanup;
4747
}
4848
if (EqualSid(TokenUserBuffer.MaybeLocalSystem.User.Sid, LocalSystemSid))

api/logger.c

Lines changed: 77 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55

66
#include "logger.h"
77
#include <Windows.h>
8+
#include <winternl.h>
89
#include <wchar.h>
910

1011
static BOOL CALLBACK
@@ -25,6 +26,13 @@ WintunSetLogger(_In_ WINTUN_LOGGER_CALLBACK NewLogger)
2526
Logger = NewLogger;
2627
}
2728

29+
static VOID
30+
StrTruncate(_Inout_count_(StrChars) WCHAR *Str, _In_ SIZE_T StrChars)
31+
{
32+
Str[StrChars - 2] = L'\u2026'; /* Horizontal Ellipsis */
33+
Str[StrChars - 1] = 0;
34+
}
35+
2836
_Post_equals_last_error_ DWORD
2937
LoggerLog(_In_ WINTUN_LOGGER_LEVEL Level, _In_z_ const WCHAR *Function, _In_z_ const WCHAR *LogLine)
3038
{
@@ -33,10 +41,7 @@ LoggerLog(_In_ WINTUN_LOGGER_LEVEL Level, _In_z_ const WCHAR *Function, _In_z_ c
3341
{
3442
WCHAR Combined[0x400];
3543
if (_snwprintf_s(Combined, _countof(Combined), _TRUNCATE, L"%s: %s", Function, LogLine) == -1)
36-
{
37-
Combined[_countof(Combined) - 2] = L'\u2026'; /* Horizontal Ellipsis */
38-
Combined[_countof(Combined) - 1] = 0;
39-
}
44+
StrTruncate(Combined, _countof(Combined));
4045
Logger(Level, Combined);
4146
}
4247
else
@@ -46,7 +51,26 @@ LoggerLog(_In_ WINTUN_LOGGER_LEVEL Level, _In_z_ const WCHAR *Function, _In_z_ c
4651
}
4752

4853
_Post_equals_last_error_ DWORD
49-
LoggerError(_In_z_ const WCHAR *Function, _In_z_ const WCHAR *Prefix, _In_ DWORD Error)
54+
LoggerLogV(
55+
_In_ WINTUN_LOGGER_LEVEL Level,
56+
_In_z_ const WCHAR *Function,
57+
_In_z_ _Printf_format_string_ const WCHAR *Format,
58+
_In_ va_list Args)
59+
{
60+
DWORD LastError = GetLastError();
61+
WCHAR LogLine[0x400];
62+
if (_vsnwprintf_s(LogLine, _countof(LogLine), _TRUNCATE, Format, Args) == -1)
63+
StrTruncate(LogLine, _countof(LogLine));
64+
if (Function)
65+
LoggerLog(Level, Function, LogLine);
66+
else
67+
Logger(Level, LogLine);
68+
SetLastError(LastError);
69+
return LastError;
70+
}
71+
72+
_Post_equals_last_error_ DWORD
73+
LoggerError(_In_ DWORD Error, _In_z_ const WCHAR *Function, _In_z_ const WCHAR *Prefix)
5074
{
5175
WCHAR *SystemMessage = NULL, *FormattedMessage = NULL;
5276
FormatMessageW(
@@ -72,3 +96,51 @@ LoggerError(_In_z_ const WCHAR *Function, _In_z_ const WCHAR *Prefix, _In_ DWORD
7296
LocalFree(SystemMessage);
7397
return Error;
7498
}
99+
100+
_Post_equals_last_error_ DWORD
101+
LoggerErrorV(
102+
_In_ DWORD Error,
103+
_In_z_ const WCHAR *Function,
104+
_In_z_ _Printf_format_string_ const WCHAR *Format,
105+
_In_ va_list Args)
106+
{
107+
WCHAR Prefix[0x400];
108+
if (_vsnwprintf_s(Prefix, _countof(Prefix), _TRUNCATE, Format, Args) == -1)
109+
StrTruncate(Prefix, _countof(Prefix));
110+
return LoggerError(Error, Function, Prefix);
111+
}
112+
113+
VOID
114+
LoggerGetRegistryKeyPath(_In_ HKEY Key, _Out_cap_c_(MAX_REG_PATH) WCHAR *Path)
115+
{
116+
DWORD LastError = GetLastError();
117+
if (Key == NULL)
118+
{
119+
wcscpy_s(Path, MAX_REG_PATH, L"<null>");
120+
goto out;
121+
}
122+
if (_snwprintf_s(Path, MAX_REG_PATH, _TRUNCATE, L"0x%p", Key) == -1)
123+
StrTruncate(Path, MAX_REG_PATH);
124+
HMODULE Dll = LoadLibraryExW(L"ntdll.dll", NULL, LOAD_LIBRARY_SEARCH_SYSTEM32);
125+
if (Dll == NULL)
126+
goto out;
127+
typedef DWORD(__stdcall * NT_QUERY_KEY_FUNC)(
128+
HANDLE KeyHandle, int KeyInformationClass, PVOID KeyInformation, ULONG Length, PULONG ResultLength);
129+
NT_QUERY_KEY_FUNC NtQueryKey = (NT_QUERY_KEY_FUNC)(GetProcAddress(Dll, "NtQueryKey"));
130+
struct _KEY_NAME_INFORMATION
131+
{
132+
ULONG NameLength;
133+
WCHAR Name[MAX_REG_PATH];
134+
} Buffer;
135+
DWORD Size;
136+
if (NtQueryKey == NULL || !NT_SUCCESS(NtQueryKey(Key, 3, &Buffer, sizeof(Buffer), &Size)) ||
137+
Size < offsetof(struct _KEY_NAME_INFORMATION, Name) || Buffer.NameLength >= MAX_REG_PATH * sizeof(WCHAR))
138+
goto cleanupDll;
139+
Buffer.NameLength /= sizeof(WCHAR);
140+
wmemcpy_s(Path, MAX_REG_PATH, Buffer.Name, Buffer.NameLength);
141+
Path[Buffer.NameLength] = L'\0';
142+
cleanupDll:
143+
FreeLibrary(Dll);
144+
out:
145+
SetLastError(LastError);
146+
}

api/logger.h

Lines changed: 62 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,10 @@
77

88
#include "wintun.h"
99
#include "entry.h"
10+
#include "registry.h"
1011
#include <Windows.h>
12+
#include <stdarg.h>
13+
#include <wchar.h>
1114

1215
extern WINTUN_LOGGER_CALLBACK Logger;
1316

@@ -21,22 +24,73 @@ _Post_equals_last_error_ DWORD
2124
LoggerLog(_In_ WINTUN_LOGGER_LEVEL Level, _In_z_ const WCHAR *Function, _In_z_ const WCHAR *LogLine);
2225

2326
_Post_equals_last_error_ DWORD
24-
LoggerError(_In_z_ const WCHAR *Function, _In_z_ const WCHAR *Prefix, _In_ DWORD Error);
27+
LoggerLogV(
28+
_In_ WINTUN_LOGGER_LEVEL Level,
29+
_In_z_ const WCHAR *Function,
30+
_In_z_ _Printf_format_string_ const WCHAR *Format,
31+
_In_ va_list Args);
2532

2633
static inline _Post_equals_last_error_ DWORD
27-
LoggerLastError(_In_z_ const WCHAR *Function, _In_z_ const WCHAR *Prefix)
34+
LoggerLogFmt(
35+
_In_ WINTUN_LOGGER_LEVEL Level,
36+
_In_z_ const WCHAR *Function,
37+
_In_z_ _Printf_format_string_ const WCHAR *Format,
38+
...)
39+
{
40+
va_list Args;
41+
va_start(Args, Format);
42+
DWORD LastError = LoggerLogV(Level, Function, Format, Args);
43+
va_end(Args);
44+
return LastError;
45+
}
46+
47+
_Post_equals_last_error_ DWORD
48+
LoggerError(_In_ DWORD Error, _In_z_ const WCHAR *Function, _In_z_ const WCHAR *Prefix);
49+
50+
_Post_equals_last_error_ DWORD
51+
LoggerErrorV(
52+
_In_ DWORD Error,
53+
_In_z_ const WCHAR *Function,
54+
_In_z_ _Printf_format_string_ const WCHAR *Format,
55+
_In_ va_list Args);
56+
57+
static inline _Post_equals_last_error_ DWORD
58+
LoggerErrorFmt(_In_ DWORD Error, _In_z_ const WCHAR *Function, _In_z_ _Printf_format_string_ const WCHAR *Format, ...)
59+
{
60+
va_list Args;
61+
va_start(Args, Format);
62+
DWORD LastError = LoggerErrorV(Error, Function, Format, Args);
63+
va_end(Args);
64+
return LastError;
65+
}
66+
67+
static inline _Post_equals_last_error_ DWORD
68+
LoggerLastErrorV(_In_z_ const WCHAR *Function, _In_z_ _Printf_format_string_ const WCHAR *Format, _In_ va_list Args)
2869
{
2970
DWORD LastError = GetLastError();
30-
LoggerError(Function, Prefix, LastError);
71+
LoggerErrorV(LastError, Function, Format, Args);
3172
SetLastError(LastError);
3273
return LastError;
3374
}
3475

76+
static inline _Post_equals_last_error_ DWORD
77+
LoggerLastErrorFmt(_In_z_ const WCHAR *Function, _In_z_ _Printf_format_string_ const WCHAR *Format, ...)
78+
{
79+
va_list Args;
80+
va_start(Args, Format);
81+
DWORD LastError = LoggerLastErrorV(Function, Format, Args);
82+
va_end(Args);
83+
return LastError;
84+
}
85+
86+
VOID
87+
LoggerGetRegistryKeyPath(_In_ HKEY Key, _Out_cap_c_(MAX_REG_PATH) WCHAR *Path);
88+
3589
#define __L(x) L##x
3690
#define _L(x) __L(x)
37-
#define LOG(lvl, msg) (LoggerLog((lvl), _L(__FUNCTION__), msg))
38-
#define LOG_ERROR(msg, err) (LoggerError(_L(__FUNCTION__), msg, (err)))
39-
#define LOG_LAST_ERROR(msg) (LoggerLastError(_L(__FUNCTION__), msg))
91+
#define LOG(lvl, msg, ...) (LoggerLogFmt((lvl), _L(__FUNCTION__), msg, __VA_ARGS__))
92+
#define LOG_ERROR(err, msg, ...) (LoggerErrorFmt((err), _L(__FUNCTION__), msg, __VA_ARGS__))
93+
#define LOG_LAST_ERROR(msg, ...) (LoggerLastErrorFmt(_L(__FUNCTION__), msg, __VA_ARGS__))
4094

4195
#define RET_ERROR(Ret, Error) ((Error) == ERROR_SUCCESS ? (Ret) : (SetLastError(Error), 0))
4296

@@ -46,13 +100,14 @@ static inline _Return_type_success_(return != NULL) _Ret_maybenull_
46100
void *Data = HeapAlloc(ModuleHeap, Flags, Size);
47101
if (!Data)
48102
{
49-
LoggerLog(WINTUN_LOG_ERR, Function, L"Out of memory");
103+
LoggerLogFmt(WINTUN_LOG_ERR, Function, L"Out of memory (flags: 0x%x, requested size: 0x%zx)", Flags, Size);
50104
SetLastError(ERROR_OUTOFMEMORY);
51105
}
52106
return Data;
53107
}
54108
#define Alloc(Size) LoggerAlloc(_L(__FUNCTION__), 0, Size)
55109
#define Zalloc(Size) LoggerAlloc(_L(__FUNCTION__), HEAP_ZERO_MEMORY, Size)
110+
56111
static inline void
57112
Free(void *Ptr)
58113
{

api/namespace.c

Lines changed: 15 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ static _Return_type_success_(
3232
Free(Str);
3333
if (GetLastError() != ERROR_INSUFFICIENT_BUFFER)
3434
{
35-
LOG_LAST_ERROR(L"Failed");
35+
LOG_LAST_ERROR(L"Failed: %s", Source);
3636
return NULL;
3737
}
3838
Len = -Len;
@@ -53,7 +53,7 @@ static _Return_type_success_(return != FALSE) BOOL NamespaceRuntimeInit(void)
5353
NTSTATUS Status;
5454
if (!BCRYPT_SUCCESS(Status = BCryptOpenAlgorithmProvider(&AlgProvider, BCRYPT_SHA256_ALGORITHM, NULL, 0)))
5555
{
56-
LOG(WINTUN_LOG_ERR, L"Failed to open algorithm provider");
56+
LOG(WINTUN_LOG_ERR, L"Failed to open algorithm provider (status: 0x%x)", Status);
5757
LastError = RtlNtStatusToDosError(Status);
5858
goto cleanupLeaveCriticalSection;
5959
}
@@ -88,10 +88,10 @@ static _Return_type_success_(return != FALSE) BOOL NamespaceRuntimeInit(void)
8888
break;
8989
if ((LastError = GetLastError()) == ERROR_PATH_NOT_FOUND)
9090
continue;
91-
LOG_ERROR(L"Failed to open private namespace", LastError);
91+
LOG_ERROR(LastError, L"Failed to open private namespace");
9292
}
9393
else
94-
LOG_ERROR(L"Failed to create private namespace", LastError);
94+
LOG_ERROR(LastError, L"Failed to create private namespace");
9595
goto cleanupBoundaryDescriptor;
9696
}
9797

@@ -118,7 +118,7 @@ _Return_type_success_(return != NULL) HANDLE NamespaceTakePoolMutex(_In_z_ const
118118
NTSTATUS Status;
119119
if (!BCRYPT_SUCCESS(Status = BCryptCreateHash(AlgProvider, &Sha256, NULL, 0, NULL, 0, 0)))
120120
{
121-
LOG(WINTUN_LOG_ERR, L"Failed to create hash");
121+
LOG(WINTUN_LOG_ERR, L"Failed to create hash (status: 0x%x)", Status);
122122
SetLastError(RtlNtStatusToDosError(Status));
123123
return NULL;
124124
}
@@ -127,7 +127,7 @@ _Return_type_success_(return != NULL) HANDLE NamespaceTakePoolMutex(_In_z_ const
127127
if (!BCRYPT_SUCCESS(
128128
Status = BCryptHashData(Sha256, (PUCHAR)mutex_label, sizeof(mutex_label) /* Including NULL 2 bytes */, 0)))
129129
{
130-
LOG(WINTUN_LOG_ERR, L"Failed to hash data");
130+
LOG(WINTUN_LOG_ERR, L"Failed to hash data (status: 0x%x)", Status);
131131
LastError = RtlNtStatusToDosError(Status);
132132
goto cleanupSha256;
133133
}
@@ -140,14 +140,14 @@ _Return_type_success_(return != NULL) HANDLE NamespaceTakePoolMutex(_In_z_ const
140140
if (!BCRYPT_SUCCESS(
141141
Status = BCryptHashData(Sha256, (PUCHAR)PoolNorm, (int)wcslen(PoolNorm) + 2 /* Add in NULL 2 bytes */, 0)))
142142
{
143-
LOG(WINTUN_LOG_ERR, L"Failed to hash data");
143+
LOG(WINTUN_LOG_ERR, L"Failed to hash data (status: 0x%x)", Status);
144144
LastError = RtlNtStatusToDosError(Status);
145145
goto cleanupPoolNorm;
146146
}
147147
BYTE Hash[32];
148148
if (!BCRYPT_SUCCESS(Status = BCryptFinishHash(Sha256, Hash, sizeof(Hash), 0)))
149149
{
150-
LOG(WINTUN_LOG_ERR, L"Failed to calculate hash");
150+
LOG(WINTUN_LOG_ERR, L"Failed to calculate hash (status: 0x%x)", Status);
151151
LastError = RtlNtStatusToDosError(Status);
152152
goto cleanupPoolNorm;
153153
}
@@ -159,18 +159,19 @@ _Return_type_success_(return != NULL) HANDLE NamespaceTakePoolMutex(_In_z_ const
159159
HANDLE Mutex = CreateMutexW(&SecurityAttributes, FALSE, MutexName);
160160
if (!Mutex)
161161
{
162-
LastError = LOG_LAST_ERROR(L"Failed to create mutex");
162+
LastError = LOG_LAST_ERROR(L"Failed to create mutex %s", MutexName);
163163
goto cleanupPoolNorm;
164164
}
165-
switch (WaitForSingleObject(Mutex, INFINITE))
165+
DWORD Result = WaitForSingleObject(Mutex, INFINITE);
166+
switch (Result)
166167
{
167168
case WAIT_OBJECT_0:
168169
case WAIT_ABANDONED:
169170
Free(PoolNorm);
170171
BCryptDestroyHash(Sha256);
171172
return Mutex;
172173
}
173-
LOG(WINTUN_LOG_ERR, L"Failed to get mutex");
174+
LOG(WINTUN_LOG_ERR, L"Failed to get mutex %s (status: 0x%x)", MutexName, Result);
174175
LastError = ERROR_GEN_FAILURE;
175176
CloseHandle(Mutex);
176177
cleanupPoolNorm:
@@ -192,13 +193,14 @@ _Return_type_success_(return != NULL) HANDLE NamespaceTakeDriverInstallationMute
192193
LOG_LAST_ERROR(L"Failed to create mutex");
193194
return NULL;
194195
}
195-
switch (WaitForSingleObject(Mutex, INFINITE))
196+
DWORD Result = WaitForSingleObject(Mutex, INFINITE);
197+
switch (Result)
196198
{
197199
case WAIT_OBJECT_0:
198200
case WAIT_ABANDONED:
199201
return Mutex;
200202
}
201-
LOG(WINTUN_LOG_ERR, L"Failed to get mutex");
203+
LOG(WINTUN_LOG_ERR, L"Failed to get mutex (status: 0x%x)", Result);
202204
CloseHandle(Mutex);
203205
SetLastError(ERROR_GEN_FAILURE);
204206
return NULL;

0 commit comments

Comments
 (0)