Milestone 5: deliver embedded RDP sessions and lifecycle hardening

This commit is contained in:
Keith Smith
2026-03-03 18:59:26 -07:00
parent 230a401386
commit 36006bd4aa
2941 changed files with 724359 additions and 77 deletions

View File

@@ -0,0 +1,181 @@
/**
* WinPR: Windows Portable Runtime
* WinPR Logger
*
* Copyright 2013 Marc-Andre Moreau <marcandre.moreau@gmail.com>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <winpr/config.h>
#include "Appender.h"
void WLog_Appender_Free(wLog* log, wLogAppender* appender)
{
if (!appender)
return;
if (appender->Layout)
{
WLog_Layout_Free(log, appender->Layout);
appender->Layout = nullptr;
}
DeleteCriticalSection(&appender->lock);
appender->Free(appender);
}
wLogAppender* WLog_GetLogAppender(wLog* log)
{
if (!log)
return nullptr;
if (!log->Appender)
return WLog_GetLogAppender(log->Parent);
return log->Appender;
}
BOOL WLog_OpenAppender(wLog* log)
{
int status = 0;
wLogAppender* appender = nullptr;
appender = WLog_GetLogAppender(log);
if (!appender)
return FALSE;
if (!appender->Open)
return TRUE;
if (!appender->active)
{
status = appender->Open(log, appender);
appender->active = TRUE;
}
return status;
}
BOOL WLog_CloseAppender(wLog* log)
{
int status = 0;
wLogAppender* appender = nullptr;
appender = WLog_GetLogAppender(log);
if (!appender)
return FALSE;
if (!appender->Close)
return TRUE;
if (appender->active)
{
status = appender->Close(log, appender);
appender->active = FALSE;
}
return status;
}
static wLogAppender* WLog_Appender_New(wLog* log, DWORD logAppenderType)
{
wLogAppender* appender = nullptr;
if (!log)
return nullptr;
switch (logAppenderType)
{
case WLOG_APPENDER_CONSOLE:
appender = WLog_ConsoleAppender_New(log);
break;
case WLOG_APPENDER_FILE:
appender = WLog_FileAppender_New(log);
break;
case WLOG_APPENDER_BINARY:
appender = WLog_BinaryAppender_New(log);
break;
case WLOG_APPENDER_CALLBACK:
appender = WLog_CallbackAppender_New(log);
break;
#ifdef WINPR_HAVE_SYSLOG_H
case WLOG_APPENDER_SYSLOG:
appender = WLog_SyslogAppender_New(log);
break;
#endif
#ifdef WINPR_HAVE_JOURNALD_H
case WLOG_APPENDER_JOURNALD:
appender = WLog_JournaldAppender_New(log);
break;
#endif
case WLOG_APPENDER_UDP:
appender = WLog_UdpAppender_New(log);
break;
default:
(void)fprintf(stderr, "%s: unknown handler type %" PRIu32 "\n", __func__,
logAppenderType);
appender = nullptr;
break;
}
if (!appender)
appender = WLog_ConsoleAppender_New(log);
if (!appender)
return nullptr;
if (!(appender->Layout = WLog_Layout_New(log)))
{
WLog_Appender_Free(log, appender);
return nullptr;
}
if (!InitializeCriticalSectionAndSpinCount(&appender->lock, 4000))
{
WLog_Appender_Free(log, appender);
return nullptr;
}
return appender;
}
BOOL WLog_SetLogAppenderType(wLog* log, DWORD logAppenderType)
{
if (!log)
return FALSE;
if (log->Appender)
{
WLog_Appender_Free(log, log->Appender);
log->Appender = nullptr;
}
log->Appender = WLog_Appender_New(log, logAppenderType);
return log->Appender != nullptr;
}
BOOL WLog_ConfigureAppender(wLogAppender* appender, const char* setting, void* value)
{
/* Just check the settings string is not empty */
if (!appender || !setting || (strnlen(setting, 2) == 0))
return FALSE;
if (appender->Set)
return appender->Set(appender, setting, value);
else
return FALSE;
}

View File

@@ -0,0 +1,39 @@
/**
* WinPR: Windows Portable Runtime
* WinPR Logger
*
* Copyright 2013 Marc-Andre Moreau <marcandre.moreau@gmail.com>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef WINPR_WLOG_APPENDER_PRIVATE_H
#define WINPR_WLOG_APPENDER_PRIVATE_H
#include "wlog.h"
WINPR_LOCAL void WLog_Appender_Free(wLog* log, wLogAppender* appender);
#include "FileAppender.h"
#include "ConsoleAppender.h"
#include "BinaryAppender.h"
#include "CallbackAppender.h"
#ifdef WINPR_HAVE_JOURNALD_H
#include "JournaldAppender.h"
#endif
#ifdef WINPR_HAVE_SYSLOG_H
#include "SyslogAppender.h"
#endif
#include "UdpAppender.h"
#endif /* WINPR_WLOG_APPENDER_PRIVATE_H */

View File

@@ -0,0 +1,236 @@
/**
* WinPR: Windows Portable Runtime
* WinPR Logger
*
* Copyright 2013 Marc-Andre Moreau <marcandre.moreau@gmail.com>
* Copyright 2015 Thincast Technologies GmbH
* Copyright 2015 DI (FH) Martin Haimberger <martin.haimberger@thincast.com>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <winpr/config.h>
#include "BinaryAppender.h"
#include <winpr/crt.h>
#include <winpr/assert.h>
#include <winpr/file.h>
#include <winpr/path.h>
#include <winpr/stream.h>
typedef struct
{
wLogAppender common;
char* FileName;
char* FilePath;
char* FullFileName;
FILE* FileDescriptor;
} wLogBinaryAppender;
static BOOL WLog_BinaryAppender_Open(wLog* log, wLogAppender* appender)
{
wLogBinaryAppender* binaryAppender = nullptr;
if (!log || !appender)
return FALSE;
binaryAppender = (wLogBinaryAppender*)appender;
if (!binaryAppender->FileName)
{
binaryAppender->FileName = (char*)malloc(MAX_PATH);
if (!binaryAppender->FileName)
return FALSE;
(void)sprintf_s(binaryAppender->FileName, MAX_PATH, "%" PRIu32 ".wlog",
GetCurrentProcessId());
}
if (!binaryAppender->FilePath)
{
binaryAppender->FilePath = GetKnownSubPath(KNOWN_PATH_TEMP, "wlog");
if (!binaryAppender->FilePath)
return FALSE;
}
if (!binaryAppender->FullFileName)
{
binaryAppender->FullFileName =
GetCombinedPath(binaryAppender->FilePath, binaryAppender->FileName);
if (!binaryAppender->FullFileName)
return FALSE;
}
if (!winpr_PathFileExists(binaryAppender->FilePath))
{
if (!winpr_PathMakePath(binaryAppender->FilePath, nullptr))
return FALSE;
UnixChangeFileMode(binaryAppender->FilePath, 0xFFFF);
}
binaryAppender->FileDescriptor = winpr_fopen(binaryAppender->FullFileName, "a+");
return binaryAppender->FileDescriptor != nullptr;
}
static BOOL WLog_BinaryAppender_Close(WINPR_ATTR_UNUSED wLog* log, wLogAppender* appender)
{
wLogBinaryAppender* binaryAppender = nullptr;
if (!appender)
return FALSE;
binaryAppender = (wLogBinaryAppender*)appender;
if (!binaryAppender->FileDescriptor)
return TRUE;
if (binaryAppender->FileDescriptor)
(void)fclose(binaryAppender->FileDescriptor);
binaryAppender->FileDescriptor = nullptr;
return TRUE;
}
static BOOL WLog_BinaryAppender_WriteMessage(wLog* log, wLogAppender* appender,
const wLogMessage* message)
{
FILE* fp = nullptr;
wStream* s = nullptr;
size_t MessageLength = 0;
size_t FileNameLength = 0;
size_t FunctionNameLength = 0;
size_t TextStringLength = 0;
BOOL ret = TRUE;
wLogBinaryAppender* binaryAppender = nullptr;
if (!log || !appender || !message)
return FALSE;
binaryAppender = (wLogBinaryAppender*)appender;
fp = binaryAppender->FileDescriptor;
if (!fp)
return FALSE;
FileNameLength = strnlen(message->FileName, INT_MAX);
FunctionNameLength = strnlen(message->FunctionName, INT_MAX);
TextStringLength = strnlen(message->TextString, INT_MAX);
MessageLength =
16 + (4 + FileNameLength + 1) + (4 + FunctionNameLength + 1) + (4 + TextStringLength + 1);
if ((MessageLength > UINT32_MAX) || (FileNameLength > UINT32_MAX) ||
(FunctionNameLength > UINT32_MAX) || (TextStringLength > UINT32_MAX))
return FALSE;
s = Stream_New(nullptr, MessageLength);
if (!s)
return FALSE;
Stream_Write_UINT32(s, (UINT32)MessageLength);
Stream_Write_UINT32(s, message->Type);
Stream_Write_UINT32(s, message->Level);
WINPR_ASSERT(message->LineNumber <= UINT32_MAX);
Stream_Write_UINT32(s, (UINT32)message->LineNumber);
Stream_Write_UINT32(s, (UINT32)FileNameLength);
Stream_Write(s, message->FileName, FileNameLength + 1);
Stream_Write_UINT32(s, (UINT32)FunctionNameLength);
Stream_Write(s, message->FunctionName, FunctionNameLength + 1);
Stream_Write_UINT32(s, (UINT32)TextStringLength);
Stream_Write(s, message->TextString, TextStringLength + 1);
Stream_SealLength(s);
if (fwrite(Stream_Buffer(s), MessageLength, 1, fp) != 1)
ret = FALSE;
Stream_Free(s, TRUE);
return ret;
}
static BOOL WLog_BinaryAppender_WriteDataMessage(WINPR_ATTR_UNUSED wLog* log,
WINPR_ATTR_UNUSED wLogAppender* appender,
WINPR_ATTR_UNUSED const wLogMessage* message)
{
return TRUE;
}
static BOOL WLog_BinaryAppender_WriteImageMessage(WINPR_ATTR_UNUSED wLog* log,
WINPR_ATTR_UNUSED wLogAppender* appender,
WINPR_ATTR_UNUSED const wLogMessage* message)
{
return TRUE;
}
static BOOL WLog_BinaryAppender_Set(wLogAppender* appender, const char* setting, void* value)
{
wLogBinaryAppender* binaryAppender = (wLogBinaryAppender*)appender;
/* Just check if the value string is longer than 0 */
if (!value || (strnlen(value, 2) == 0))
return FALSE;
if (!strcmp("outputfilename", setting))
{
binaryAppender->FileName = _strdup((const char*)value);
if (!binaryAppender->FileName)
return FALSE;
}
else if (!strcmp("outputfilepath", setting))
{
binaryAppender->FilePath = _strdup((const char*)value);
if (!binaryAppender->FilePath)
return FALSE;
}
else
return FALSE;
return TRUE;
}
static void WLog_BinaryAppender_Free(wLogAppender* appender)
{
wLogBinaryAppender* binaryAppender = nullptr;
if (appender)
{
binaryAppender = (wLogBinaryAppender*)appender;
free(binaryAppender->FileName);
free(binaryAppender->FilePath);
free(binaryAppender->FullFileName);
free(binaryAppender);
}
}
wLogAppender* WLog_BinaryAppender_New(WINPR_ATTR_UNUSED wLog* log)
{
wLogBinaryAppender* BinaryAppender = (wLogBinaryAppender*)calloc(1, sizeof(wLogBinaryAppender));
if (!BinaryAppender)
return nullptr;
BinaryAppender->common.Type = WLOG_APPENDER_BINARY;
BinaryAppender->common.Open = WLog_BinaryAppender_Open;
BinaryAppender->common.Close = WLog_BinaryAppender_Close;
BinaryAppender->common.WriteMessage = WLog_BinaryAppender_WriteMessage;
BinaryAppender->common.WriteDataMessage = WLog_BinaryAppender_WriteDataMessage;
BinaryAppender->common.WriteImageMessage = WLog_BinaryAppender_WriteImageMessage;
BinaryAppender->common.Free = WLog_BinaryAppender_Free;
BinaryAppender->common.Set = WLog_BinaryAppender_Set;
return &BinaryAppender->common;
}

View File

@@ -0,0 +1,29 @@
/**
* WinPR: Windows Portable Runtime
* WinPR Logger
*
* Copyright 2013 Marc-Andre Moreau <marcandre.moreau@gmail.com>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef WINPR_WLOG_BINARY_APPENDER_PRIVATE_H
#define WINPR_WLOG_BINARY_APPENDER_PRIVATE_H
#include "wlog.h"
WINPR_ATTR_MALLOC(WLog_Appender_Free, 2)
WINPR_ATTR_NODISCARD
WINPR_LOCAL wLogAppender* WLog_BinaryAppender_New(wLog* log);
#endif /* WINPR_WLOG_BINARY_APPENDER_PRIVATE_H */

View File

@@ -0,0 +1,175 @@
/**
* WinPR: Windows Portable Runtime
* WinPR Logger
*
* Copyright 2014 Armin Novak <armin.novak@thincast.com>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <winpr/config.h>
#include "CallbackAppender.h"
typedef struct
{
wLogAppender common;
wLogCallbacks* callbacks;
} wLogCallbackAppender;
static BOOL WLog_CallbackAppender_Open(WINPR_ATTR_UNUSED wLog* log,
WINPR_ATTR_UNUSED wLogAppender* appender)
{
return TRUE;
}
static BOOL WLog_CallbackAppender_Close(WINPR_ATTR_UNUSED wLog* log,
WINPR_ATTR_UNUSED wLogAppender* appender)
{
return TRUE;
}
static BOOL WLog_CallbackAppender_WriteMessage(wLog* log, wLogAppender* appender,
const wLogMessage* cmessage)
{
WINPR_ASSERT(cmessage);
if (!appender)
return FALSE;
char prefix[WLOG_MAX_PREFIX_SIZE] = WINPR_C_ARRAY_INIT;
WLog_Layout_GetMessagePrefix(log, appender->Layout, cmessage, prefix, sizeof(prefix));
wLogCallbackAppender* callbackAppender = (wLogCallbackAppender*)appender;
if (callbackAppender->callbacks && callbackAppender->callbacks->message)
{
wLogMessage message = *cmessage;
message.PrefixString = prefix;
return callbackAppender->callbacks->message(&message);
}
else
return FALSE;
}
static BOOL WLog_CallbackAppender_WriteDataMessage(wLog* log, wLogAppender* appender,
const wLogMessage* cmessage)
{
if (!appender)
return FALSE;
char prefix[WLOG_MAX_PREFIX_SIZE] = WINPR_C_ARRAY_INIT;
WLog_Layout_GetMessagePrefix(log, appender->Layout, cmessage, prefix, sizeof(prefix));
wLogCallbackAppender* callbackAppender = (wLogCallbackAppender*)appender;
if (callbackAppender->callbacks && callbackAppender->callbacks->data)
{
wLogMessage message = *cmessage;
message.PrefixString = prefix;
return callbackAppender->callbacks->data(&message);
}
else
return FALSE;
}
static BOOL WLog_CallbackAppender_WriteImageMessage(wLog* log, wLogAppender* appender,
const wLogMessage* cmessage)
{
WINPR_ASSERT(cmessage);
if (!appender)
return FALSE;
char prefix[WLOG_MAX_PREFIX_SIZE] = WINPR_C_ARRAY_INIT;
WLog_Layout_GetMessagePrefix(log, appender->Layout, cmessage, prefix, sizeof(prefix));
wLogCallbackAppender* callbackAppender = (wLogCallbackAppender*)appender;
if (callbackAppender->callbacks && callbackAppender->callbacks->image)
{
wLogMessage message = *cmessage;
message.PrefixString = prefix;
return callbackAppender->callbacks->image(&message);
}
else
return FALSE;
}
static BOOL WLog_CallbackAppender_WritePacketMessage(wLog* log, wLogAppender* appender,
const wLogMessage* cmessage)
{
WINPR_ASSERT(cmessage);
if (!appender)
return FALSE;
char prefix[WLOG_MAX_PREFIX_SIZE] = WINPR_C_ARRAY_INIT;
WLog_Layout_GetMessagePrefix(log, appender->Layout, cmessage, prefix, sizeof(prefix));
wLogCallbackAppender* callbackAppender = (wLogCallbackAppender*)appender;
if (callbackAppender->callbacks && callbackAppender->callbacks->package)
{
wLogMessage message = *cmessage;
message.PrefixString = prefix;
return callbackAppender->callbacks->package(&message);
}
else
return FALSE;
}
static BOOL WLog_CallbackAppender_Set(wLogAppender* appender, const char* setting, void* value)
{
wLogCallbackAppender* callbackAppender = (wLogCallbackAppender*)appender;
if (!value || (strcmp(setting, "callbacks") != 0))
return FALSE;
if (!(callbackAppender->callbacks = calloc(1, sizeof(wLogCallbacks))))
{
return FALSE;
}
callbackAppender->callbacks = memcpy(callbackAppender->callbacks, value, sizeof(wLogCallbacks));
return TRUE;
}
static void WLog_CallbackAppender_Free(wLogAppender* appender)
{
wLogCallbackAppender* callbackAppender = nullptr;
if (!appender)
{
return;
}
callbackAppender = (wLogCallbackAppender*)appender;
free(callbackAppender->callbacks);
free(appender);
}
wLogAppender* WLog_CallbackAppender_New(WINPR_ATTR_UNUSED wLog* log)
{
wLogCallbackAppender* CallbackAppender =
(wLogCallbackAppender*)calloc(1, sizeof(wLogCallbackAppender));
if (!CallbackAppender)
return nullptr;
CallbackAppender->common.Type = WLOG_APPENDER_CALLBACK;
CallbackAppender->common.Open = WLog_CallbackAppender_Open;
CallbackAppender->common.Close = WLog_CallbackAppender_Close;
CallbackAppender->common.WriteMessage = WLog_CallbackAppender_WriteMessage;
CallbackAppender->common.WriteDataMessage = WLog_CallbackAppender_WriteDataMessage;
CallbackAppender->common.WriteImageMessage = WLog_CallbackAppender_WriteImageMessage;
CallbackAppender->common.WritePacketMessage = WLog_CallbackAppender_WritePacketMessage;
CallbackAppender->common.Free = WLog_CallbackAppender_Free;
CallbackAppender->common.Set = WLog_CallbackAppender_Set;
return &CallbackAppender->common;
}

View File

@@ -0,0 +1,29 @@
/**
* WinPR: Windows Portable Runtime
* WinPR Logger
*
* Copyright 2014 Armin Novak <armin.novak@thincast.com>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef WINPR_WLOG_CALLBACK_APPENDER_PRIVATE_H
#define WINPR_WLOG_CALLBACK_APPENDER_PRIVATE_H
#include "wlog.h"
WINPR_ATTR_MALLOC(WLog_Appender_Free, 2)
WINPR_ATTR_NODISCARD
WINPR_LOCAL wLogAppender* WLog_CallbackAppender_New(wLog* log);
#endif /* WINPR_WLOG_CALLBACK_APPENDER_PRIVATE_H */

View File

@@ -0,0 +1,276 @@
/**
* WinPR: Windows Portable Runtime
* WinPR Logger
*
* Copyright 2013 Marc-Andre Moreau <marcandre.moreau@gmail.com>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <winpr/config.h>
#include "ConsoleAppender.h"
#include "Message.h"
#ifdef ANDROID
#include <android/log.h>
#endif
#define WLOG_CONSOLE_DEFAULT 0
#define WLOG_CONSOLE_STDOUT 1
#define WLOG_CONSOLE_STDERR 2
#define WLOG_CONSOLE_DEBUG 4
typedef struct
{
wLogAppender common;
int outputStream;
} wLogConsoleAppender;
static BOOL WLog_ConsoleAppender_Open(WINPR_ATTR_UNUSED wLog* log,
WINPR_ATTR_UNUSED wLogAppender* appender)
{
return TRUE;
}
static BOOL WLog_ConsoleAppender_Close(WINPR_ATTR_UNUSED wLog* log,
WINPR_ATTR_UNUSED wLogAppender* appender)
{
return TRUE;
}
static BOOL WLog_ConsoleAppender_WriteMessage(wLog* log, wLogAppender* appender,
const wLogMessage* cmessage)
{
if (!appender)
return FALSE;
wLogConsoleAppender* consoleAppender = (wLogConsoleAppender*)appender;
char prefix[WLOG_MAX_PREFIX_SIZE] = WINPR_C_ARRAY_INIT;
WLog_Layout_GetMessagePrefix(log, appender->Layout, cmessage, prefix, sizeof(prefix));
#ifdef _WIN32
if (consoleAppender->outputStream == WLOG_CONSOLE_DEBUG)
{
OutputDebugStringA(prefix);
OutputDebugStringA(cmessage->TextString);
OutputDebugStringA("\n");
return TRUE;
}
#endif
#ifdef ANDROID
android_LogPriority level;
switch (cmessage->Level)
{
case WLOG_TRACE:
level = ANDROID_LOG_VERBOSE;
break;
case WLOG_DEBUG:
level = ANDROID_LOG_DEBUG;
break;
case WLOG_INFO:
level = ANDROID_LOG_INFO;
break;
case WLOG_WARN:
level = ANDROID_LOG_WARN;
break;
case WLOG_ERROR:
level = ANDROID_LOG_ERROR;
break;
case WLOG_FATAL:
level = ANDROID_LOG_FATAL;
break;
case WLOG_OFF:
level = ANDROID_LOG_SILENT;
break;
default:
level = ANDROID_LOG_FATAL;
break;
}
if (level != ANDROID_LOG_SILENT)
__android_log_print(level, log->Name, "%s%s", prefix, cmessage->TextString);
#else
FILE* fp = nullptr;
switch (consoleAppender->outputStream)
{
case WLOG_CONSOLE_STDOUT:
fp = stdout;
break;
case WLOG_CONSOLE_STDERR:
fp = stderr;
break;
default:
switch (cmessage->Level)
{
case WLOG_TRACE:
case WLOG_DEBUG:
case WLOG_INFO:
fp = stdout;
break;
default:
fp = stderr;
break;
}
break;
}
if (cmessage->Level != WLOG_OFF)
(void)fprintf(fp, "%s%s\n", prefix, cmessage->TextString);
#endif
return TRUE;
}
static int g_DataId = 0;
static BOOL WLog_ConsoleAppender_WriteDataMessage(WINPR_ATTR_UNUSED wLog* log,
WINPR_ATTR_UNUSED wLogAppender* appender,
const wLogMessage* message)
{
#if defined(ANDROID)
return FALSE;
#else
int DataId = 0;
char* FullFileName = nullptr;
DataId = g_DataId++;
FullFileName = WLog_Message_GetOutputFileName(DataId, "dat");
WLog_DataMessage_Write(FullFileName, message->Data, message->Length);
free(FullFileName);
return TRUE;
#endif
}
static int g_ImageId = 0;
static BOOL WLog_ConsoleAppender_WriteImageMessage(WINPR_ATTR_UNUSED wLog* log,
WINPR_ATTR_UNUSED wLogAppender* appender,
const wLogMessage* message)
{
#if defined(ANDROID)
return FALSE;
#else
int ImageId = 0;
char* FullFileName = nullptr;
ImageId = g_ImageId++;
FullFileName = WLog_Message_GetOutputFileName(ImageId, "bmp");
WLog_ImageMessage_Write(FullFileName, message->ImageData, message->ImageWidth,
message->ImageHeight, message->ImageBpp);
free(FullFileName);
return TRUE;
#endif
}
static int g_PacketId = 0;
static BOOL WLog_ConsoleAppender_WritePacketMessage(WINPR_ATTR_UNUSED wLog* log,
wLogAppender* appender,
const wLogMessage* message)
{
#if defined(ANDROID)
return FALSE;
#else
char* FullFileName = nullptr;
g_PacketId++;
if (!appender->PacketMessageContext)
{
FullFileName = WLog_Message_GetOutputFileName(-1, "pcap");
appender->PacketMessageContext = (void*)Pcap_Open(FullFileName, TRUE);
free(FullFileName);
}
if (appender->PacketMessageContext)
return WLog_PacketMessage_Write((wPcap*)appender->PacketMessageContext, message->PacketData,
message->PacketLength, message->PacketFlags);
return TRUE;
#endif
}
static BOOL WLog_ConsoleAppender_Set(wLogAppender* appender, const char* setting, void* value)
{
wLogConsoleAppender* consoleAppender = (wLogConsoleAppender*)appender;
/* Just check the value string is not empty */
if (!value || (strnlen(value, 2) == 0))
return FALSE;
if (strcmp("outputstream", setting) != 0)
return FALSE;
if (!strcmp("stdout", value))
consoleAppender->outputStream = WLOG_CONSOLE_STDOUT;
else if (!strcmp("stderr", value))
consoleAppender->outputStream = WLOG_CONSOLE_STDERR;
else if (!strcmp("default", value))
consoleAppender->outputStream = WLOG_CONSOLE_DEFAULT;
else if (!strcmp("debug", value))
consoleAppender->outputStream = WLOG_CONSOLE_DEBUG;
else
return FALSE;
return TRUE;
}
static void WLog_ConsoleAppender_Free(wLogAppender* appender)
{
if (appender)
{
if (appender->PacketMessageContext)
{
Pcap_Close((wPcap*)appender->PacketMessageContext);
}
free(appender);
}
}
wLogAppender* WLog_ConsoleAppender_New(WINPR_ATTR_UNUSED wLog* log)
{
wLogConsoleAppender* ConsoleAppender =
(wLogConsoleAppender*)calloc(1, sizeof(wLogConsoleAppender));
if (!ConsoleAppender)
return nullptr;
ConsoleAppender->common.Type = WLOG_APPENDER_CONSOLE;
ConsoleAppender->common.Open = WLog_ConsoleAppender_Open;
ConsoleAppender->common.Close = WLog_ConsoleAppender_Close;
ConsoleAppender->common.WriteMessage = WLog_ConsoleAppender_WriteMessage;
ConsoleAppender->common.WriteDataMessage = WLog_ConsoleAppender_WriteDataMessage;
ConsoleAppender->common.WriteImageMessage = WLog_ConsoleAppender_WriteImageMessage;
ConsoleAppender->common.WritePacketMessage = WLog_ConsoleAppender_WritePacketMessage;
ConsoleAppender->common.Set = WLog_ConsoleAppender_Set;
ConsoleAppender->common.Free = WLog_ConsoleAppender_Free;
ConsoleAppender->outputStream = WLOG_CONSOLE_DEFAULT;
#ifdef _WIN32
if (IsDebuggerPresent())
ConsoleAppender->outputStream = WLOG_CONSOLE_DEBUG;
#endif
return &ConsoleAppender->common;
}

View File

@@ -0,0 +1,29 @@
/**
* WinPR: Windows Portable Runtime
* WinPR Logger
*
* Copyright 2013 Marc-Andre Moreau <marcandre.moreau@gmail.com>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef WINPR_WLOG_CONSOLE_APPENDER_PRIVATE_H
#define WINPR_WLOG_CONSOLE_APPENDER_PRIVATE_H
#include "wlog.h"
WINPR_ATTR_MALLOC(WLog_Appender_Free, 2)
WINPR_ATTR_NODISCARD
WINPR_LOCAL wLogAppender* WLog_ConsoleAppender_New(wLog* log);
#endif /* WINPR_WLOG_CONSOLE_APPENDER_PRIVATE_H */

View File

@@ -0,0 +1,42 @@
/**
* WinPR: Windows Portable Runtime
* WinPR Logger
*
* Copyright 2013 Marc-Andre Moreau <marcandre.moreau@gmail.com>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <winpr/config.h>
#include "wlog.h"
#include "DataMessage.h"
#include <winpr/file.h>
BOOL WLog_DataMessage_Write(const char* filename, const void* data, size_t length)
{
FILE* fp = nullptr;
BOOL ret = TRUE;
fp = winpr_fopen(filename, "w+b");
if (!fp)
return FALSE;
if (fwrite(data, length, 1, fp) != 1)
ret = FALSE;
(void)fclose(fp);
return ret;
}

View File

@@ -0,0 +1,25 @@
/**
* WinPR: Windows Portable Runtime
* WinPR Logger
*
* Copyright 2013 Marc-Andre Moreau <marcandre.moreau@gmail.com>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef WINPR_WLOG_DATA_MESSAGE_PRIVATE_H
#define WINPR_WLOG_DATA_MESSAGE_PRIVATE_H
BOOL WLog_DataMessage_Write(const char* filename, const void* data, size_t length);
#endif /* WINPR_WLOG_DATA_MESSAGE_PRIVATE_H */

View File

@@ -0,0 +1,278 @@
/**
* WinPR: Windows Portable Runtime
* WinPR Logger
*
* Copyright 2013 Marc-Andre Moreau <marcandre.moreau@gmail.com>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <winpr/config.h>
#include "FileAppender.h"
#include "Message.h"
#include <winpr/crt.h>
#include <winpr/environment.h>
#include <winpr/file.h>
#include <winpr/path.h>
typedef struct
{
wLogAppender common;
char* FileName;
char* FilePath;
char* FullFileName;
FILE* FileDescriptor;
} wLogFileAppender;
static BOOL WLog_FileAppender_SetOutputFileName(wLogFileAppender* appender, const char* filename)
{
WINPR_ASSERT(appender);
WINPR_ASSERT(filename);
appender->FileName = _strdup(filename);
return appender->FileName != nullptr;
}
static BOOL WLog_FileAppender_SetOutputFilePath(wLogFileAppender* appender, const char* filepath)
{
appender->FilePath = _strdup(filepath);
return appender->FilePath != nullptr;
}
static BOOL WLog_FileAppender_Open(wLog* log, wLogAppender* appender)
{
wLogFileAppender* fileAppender = nullptr;
if (!log || !appender)
return FALSE;
fileAppender = (wLogFileAppender*)appender;
if (!fileAppender->FilePath)
{
fileAppender->FilePath = GetKnownSubPath(KNOWN_PATH_TEMP, "wlog");
if (!fileAppender->FilePath)
return FALSE;
}
if (!fileAppender->FileName)
{
fileAppender->FileName = (char*)malloc(MAX_PATH);
if (!fileAppender->FileName)
return FALSE;
(void)sprintf_s(fileAppender->FileName, MAX_PATH, "%" PRIu32 ".log", GetCurrentProcessId());
}
if (!fileAppender->FullFileName)
{
fileAppender->FullFileName =
GetCombinedPath(fileAppender->FilePath, fileAppender->FileName);
if (!fileAppender->FullFileName)
return FALSE;
}
if (!winpr_PathFileExists(fileAppender->FilePath))
{
if (!winpr_PathMakePath(fileAppender->FilePath, nullptr))
return FALSE;
UnixChangeFileMode(fileAppender->FilePath, 0xFFFF);
}
fileAppender->FileDescriptor = winpr_fopen(fileAppender->FullFileName, "a+");
return fileAppender->FileDescriptor != nullptr;
}
static BOOL WLog_FileAppender_Close(wLog* log, wLogAppender* appender)
{
wLogFileAppender* fileAppender = nullptr;
if (!log || !appender)
return FALSE;
fileAppender = (wLogFileAppender*)appender;
if (!fileAppender->FileDescriptor)
return TRUE;
(void)fclose(fileAppender->FileDescriptor);
fileAppender->FileDescriptor = nullptr;
return TRUE;
}
static BOOL WLog_FileAppender_WriteMessage(wLog* log, wLogAppender* appender,
const wLogMessage* cmessage)
{
if (!log || !appender || !cmessage)
return FALSE;
wLogFileAppender* fileAppender = (wLogFileAppender*)appender;
FILE* fp = fileAppender->FileDescriptor;
if (!fp)
return FALSE;
char prefix[WLOG_MAX_PREFIX_SIZE] = WINPR_C_ARRAY_INIT;
WLog_Layout_GetMessagePrefix(log, appender->Layout, cmessage, prefix, sizeof(prefix));
(void)fprintf(fp, "%s%s\n", prefix, cmessage->TextString);
(void)fflush(fp); /* slow! */
return TRUE;
}
static int g_DataId = 0;
static BOOL WLog_FileAppender_WriteDataMessage(wLog* log, wLogAppender* appender,
const wLogMessage* message)
{
int DataId = 0;
char* FullFileName = nullptr;
if (!log || !appender || !message)
return FALSE;
DataId = g_DataId++;
FullFileName = WLog_Message_GetOutputFileName(DataId, "dat");
WLog_DataMessage_Write(FullFileName, message->Data, message->Length);
free(FullFileName);
return TRUE;
}
static int g_ImageId = 0;
static BOOL WLog_FileAppender_WriteImageMessage(wLog* log, wLogAppender* appender,
const wLogMessage* message)
{
int ImageId = 0;
char* FullFileName = nullptr;
if (!log || !appender || !message)
return FALSE;
ImageId = g_ImageId++;
FullFileName = WLog_Message_GetOutputFileName(ImageId, "bmp");
WLog_ImageMessage_Write(FullFileName, message->ImageData, message->ImageWidth,
message->ImageHeight, message->ImageBpp);
free(FullFileName);
return TRUE;
}
static BOOL WLog_FileAppender_Set(wLogAppender* appender, const char* setting, void* value)
{
wLogFileAppender* fileAppender = (wLogFileAppender*)appender;
/* Just check the value string is not empty */
if (!value || (strnlen(value, 2) == 0))
return FALSE;
if (!strcmp("outputfilename", setting))
return WLog_FileAppender_SetOutputFileName(fileAppender, (const char*)value);
if (!strcmp("outputfilepath", setting))
return WLog_FileAppender_SetOutputFilePath(fileAppender, (const char*)value);
return FALSE;
}
static void WLog_FileAppender_Free(wLogAppender* appender)
{
wLogFileAppender* fileAppender = nullptr;
if (appender)
{
fileAppender = (wLogFileAppender*)appender;
free(fileAppender->FileName);
free(fileAppender->FilePath);
free(fileAppender->FullFileName);
free(fileAppender);
}
}
wLogAppender* WLog_FileAppender_New(WINPR_ATTR_UNUSED wLog* log)
{
LPSTR env = nullptr;
LPCSTR name = nullptr;
DWORD nSize = 0;
wLogFileAppender* FileAppender = nullptr;
FileAppender = (wLogFileAppender*)calloc(1, sizeof(wLogFileAppender));
if (!FileAppender)
return nullptr;
FileAppender->common.Type = WLOG_APPENDER_FILE;
FileAppender->common.Open = WLog_FileAppender_Open;
FileAppender->common.Close = WLog_FileAppender_Close;
FileAppender->common.WriteMessage = WLog_FileAppender_WriteMessage;
FileAppender->common.WriteDataMessage = WLog_FileAppender_WriteDataMessage;
FileAppender->common.WriteImageMessage = WLog_FileAppender_WriteImageMessage;
FileAppender->common.Free = WLog_FileAppender_Free;
FileAppender->common.Set = WLog_FileAppender_Set;
name = "WLOG_FILEAPPENDER_OUTPUT_FILE_PATH";
nSize = GetEnvironmentVariableA(name, nullptr, 0);
if (nSize)
{
BOOL status = 0;
env = (LPSTR)malloc(nSize);
if (!env)
goto error_free;
if (GetEnvironmentVariableA(name, env, nSize) != nSize - 1)
{
free(env);
goto error_free;
}
status = WLog_FileAppender_SetOutputFilePath(FileAppender, env);
free(env);
if (!status)
goto error_free;
}
name = "WLOG_FILEAPPENDER_OUTPUT_FILE_NAME";
nSize = GetEnvironmentVariableA(name, nullptr, 0);
if (nSize)
{
BOOL status = FALSE;
env = (LPSTR)malloc(nSize);
if (!env)
goto error_output_file_name;
if (GetEnvironmentVariableA(name, env, nSize) == nSize - 1)
status = WLog_FileAppender_SetOutputFileName(FileAppender, env);
free(env);
if (!status)
goto error_output_file_name;
}
return (wLogAppender*)FileAppender;
error_output_file_name:
free(FileAppender->FilePath);
error_free:
free(FileAppender);
return nullptr;
}

View File

@@ -0,0 +1,29 @@
/**
* WinPR: Windows Portable Runtime
* WinPR Logger
*
* Copyright 2013 Marc-Andre Moreau <marcandre.moreau@gmail.com>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef WINPR_WLOG_FILE_APPENDER_PRIVATE_H
#define WINPR_WLOG_FILE_APPENDER_PRIVATE_H
#include "wlog.h"
WINPR_ATTR_MALLOC(WLog_Appender_Free, 2)
WINPR_ATTR_NODISCARD
WINPR_LOCAL wLogAppender* WLog_FileAppender_New(wLog* log);
#endif /* WINPR_WLOG_FILE_APPENDER_PRIVATE_H */

View File

@@ -0,0 +1,31 @@
/**
* WinPR: Windows Portable Runtime
* WinPR Logger
*
* Copyright 2013 Marc-Andre Moreau <marcandre.moreau@gmail.com>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <winpr/config.h>
#include "wlog.h"
#include <winpr/image.h>
#include "ImageMessage.h"
BOOL WLog_ImageMessage_Write(char* filename, void* data, size_t width, size_t height, size_t bpp)
{
const int status = winpr_bitmap_write(filename, data, width, height, bpp);
return (status >= 0);
}

View File

@@ -0,0 +1,25 @@
/**
* WinPR: Windows Portable Runtime
* WinPR Logger
*
* Copyright 2013 Marc-Andre Moreau <marcandre.moreau@gmail.com>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef WINPR_WLOG_IMAGE_MESSAGE_PRIVATE_H
#define WINPR_WLOG_IMAGE_MESSAGE_PRIVATE_H
BOOL WLog_ImageMessage_Write(char* filename, void* data, size_t width, size_t height, size_t bpp);
#endif /* WINPR_WLOG_IMAGE_MESSAGE_PRIVATE_H */

View File

@@ -0,0 +1,220 @@
/**
* WinPR: Windows Portable Runtime
* WinPR Logger
*
* Copyright © 2015 Thincast Technologies GmbH
* Copyright © 2015 David FORT <contact@hardening-consulting.com>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <winpr/config.h>
#include "JournaldAppender.h"
#include <unistd.h>
#include <syslog.h>
#include <systemd/sd-journal.h>
#include <winpr/crt.h>
#include <winpr/environment.h>
typedef struct
{
wLogAppender common;
char* identifier;
FILE* stream;
} wLogJournaldAppender;
static BOOL WLog_JournaldAppender_Open(wLog* log, wLogAppender* appender)
{
int fd = 0;
wLogJournaldAppender* journaldAppender = nullptr;
if (!log || !appender)
return FALSE;
journaldAppender = (wLogJournaldAppender*)appender;
if (journaldAppender->stream)
return TRUE;
fd = sd_journal_stream_fd(journaldAppender->identifier, LOG_INFO, 1);
if (fd < 0)
return FALSE;
journaldAppender->stream = fdopen(fd, "w");
if (!journaldAppender->stream)
{
close(fd);
return FALSE;
}
setbuffer(journaldAppender->stream, nullptr, 0);
return TRUE;
}
static BOOL WLog_JournaldAppender_Close(wLog* log, wLogAppender* appender)
{
wLogJournaldAppender* journaldAppender = (wLogJournaldAppender*)appender;
if (!log || !appender)
return FALSE;
if (journaldAppender->stream)
(void)fclose(journaldAppender->stream);
free(journaldAppender->identifier);
journaldAppender->stream = nullptr;
journaldAppender->identifier = nullptr;
return TRUE;
}
static BOOL WLog_JournaldAppender_WriteMessage(wLog* log, wLogAppender* appender,
const wLogMessage* cmessage)
{
if (!log || !appender || !cmessage)
return FALSE;
wLogJournaldAppender* journaldAppender = (wLogJournaldAppender*)appender;
const char* formatStr = nullptr;
switch (cmessage->Level)
{
case WLOG_TRACE:
case WLOG_DEBUG:
formatStr = "<7>%s%s\n";
break;
case WLOG_INFO:
formatStr = "<6>%s%s\n";
break;
case WLOG_WARN:
formatStr = "<4>%s%s\n";
break;
case WLOG_ERROR:
formatStr = "<3>%s%s\n";
break;
case WLOG_FATAL:
formatStr = "<2>%s%s\n";
break;
case WLOG_OFF:
return TRUE;
default:
(void)fprintf(stderr, "%s: unknown level %" PRIu32 "\n", __func__, cmessage->Level);
return FALSE;
}
char prefix[WLOG_MAX_PREFIX_SIZE] = WINPR_C_ARRAY_INIT;
WLog_Layout_GetMessagePrefix(log, appender->Layout, cmessage, prefix, sizeof(prefix));
if (cmessage->Level != WLOG_OFF)
{
WINPR_PRAGMA_DIAG_PUSH
WINPR_PRAGMA_DIAG_IGNORED_FORMAT_NONLITERAL(void)
fprintf(journaldAppender->stream, formatStr, prefix, cmessage->TextString);
WINPR_PRAGMA_DIAG_POP
}
return TRUE;
}
static BOOL WLog_JournaldAppender_WriteDataMessage(wLog* log, wLogAppender* appender,
const wLogMessage* message)
{
if (!log || !appender || !message)
return FALSE;
(void)fprintf(stderr, "[TODO: %s] data messages not implemented! Ignoring.\n", __func__);
return TRUE;
}
static BOOL WLog_JournaldAppender_WriteImageMessage(wLog* log, wLogAppender* appender,
const wLogMessage* message)
{
if (!log || !appender || !message)
return FALSE;
(void)fprintf(stderr, "[TODO: %s] image messages not implemented! Ignoring.\n", __func__);
return TRUE;
}
static BOOL WLog_JournaldAppender_Set(wLogAppender* appender, const char* setting, void* value)
{
wLogJournaldAppender* journaldAppender = (wLogJournaldAppender*)appender;
/* Just check the value string is not empty */
if (!value || (strnlen(value, 2) == 0))
return FALSE;
if (strcmp("identifier", setting) != 0)
return FALSE;
/* If the stream is already open the identifier can't be changed */
if (journaldAppender->stream)
return FALSE;
if (journaldAppender->identifier)
free(journaldAppender->identifier);
return ((journaldAppender->identifier = _strdup((const char*)value)) != nullptr);
}
static void WLog_JournaldAppender_Free(wLogAppender* appender)
{
wLogJournaldAppender* journaldAppender = nullptr;
if (appender)
{
journaldAppender = (wLogJournaldAppender*)appender;
if (journaldAppender->stream)
(void)fclose(journaldAppender->stream);
free(journaldAppender->identifier);
free(journaldAppender);
}
}
wLogAppender* WLog_JournaldAppender_New(wLog* log)
{
LPCSTR name = "WLOG_JOURNALD_ID";
wLogJournaldAppender* appender = (wLogJournaldAppender*)calloc(1, sizeof(wLogJournaldAppender));
if (!appender)
return nullptr;
appender->common.Type = WLOG_APPENDER_JOURNALD;
appender->common.Open = WLog_JournaldAppender_Open;
appender->common.Close = WLog_JournaldAppender_Close;
appender->common.WriteMessage = WLog_JournaldAppender_WriteMessage;
appender->common.WriteDataMessage = WLog_JournaldAppender_WriteDataMessage;
appender->common.WriteImageMessage = WLog_JournaldAppender_WriteImageMessage;
appender->common.Set = WLog_JournaldAppender_Set;
appender->common.Free = WLog_JournaldAppender_Free;
const DWORD nSize = GetEnvironmentVariableA(name, nullptr, 0);
if (nSize)
{
appender->identifier = (LPSTR)malloc(nSize);
if (!appender->identifier)
goto error_open;
if (GetEnvironmentVariableA(name, appender->identifier, nSize) != nSize - 1)
goto error_open;
if (!WLog_JournaldAppender_Open(log, (wLogAppender*)appender))
goto error_open;
}
return (wLogAppender*)appender;
error_open:
free(appender->identifier);
free(appender);
return nullptr;
}

View File

@@ -0,0 +1,31 @@
/**
* Copyright © 2015 Thincast Technologies GmbH
* Copyright © 2015 David FORT <contact@hardening-consulting.com>
*
* Permission to use, copy, modify, distribute, and sell this software and
* its documentation for any purpose is hereby granted without fee, provided
* that the above copyright notice appear in all copies and that both that
* copyright notice and this permission notice appear in supporting
* documentation, and that the name of the copyright holders not be used in
* advertising or publicity pertaining to distribution of the software
* without specific, written prior permission. The copyright holders make
* no representations about the suitability of this software for any
* purpose. It is provided "as is" without express or implied warranty.
*
* THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
* SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY
* SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
* RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
* CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#ifndef WINPR_LIBWINPR_UTILS_WLOG_JOURNALDAPPENDER_H_
#define WINPR_LIBWINPR_UTILS_WLOG_JOURNALDAPPENDER_H_
#include "wlog.h"
WINPR_LOCAL wLogAppender* WLog_JournaldAppender_New(wLog* log);
#endif /* WINPR_LIBWINPR_UTILS_WLOG_JOURNALDAPPENDER_H_ */

View File

@@ -0,0 +1,458 @@
/**
* WinPR: Windows Portable Runtime
* WinPR Logger
*
* Copyright 2013 Marc-Andre Moreau <marcandre.moreau@gmail.com>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <winpr/config.h>
#include <stdio.h>
#include <string.h>
#include <stdarg.h>
#include <winpr/crt.h>
#include <winpr/assert.h>
#include <winpr/print.h>
#include <winpr/sysinfo.h>
#include <winpr/environment.h>
#include "wlog.h"
#include "Layout.h"
#if defined __linux__ && !defined ANDROID
#include <unistd.h>
#include <sys/syscall.h>
#endif
#ifndef MIN
#define MIN(x, y) (((x) < (y)) ? (x) : (y))
#endif
struct format_option_recurse;
struct format_tid_arg
{
char tid[32];
};
struct format_option
{
const char* fmt;
size_t fmtlen;
const char* replace;
size_t replacelen;
const char* (*fkt)(void*);
union
{
void* pv;
const void* cpv;
size_t s;
} arg;
const char* (*ext)(const struct format_option* opt, const char* str, size_t* preplacelen,
size_t* pskiplen);
struct format_option_recurse* recurse;
};
struct format_option_recurse
{
struct format_option* options;
size_t nroptions;
wLog* log;
wLogLayout* layout;
const wLogMessage* message;
char buffer[WLOG_MAX_PREFIX_SIZE];
};
/**
* Log Layout
*/
WINPR_ATTR_FORMAT_ARG(3, 0)
static void WLog_PrintMessagePrefixVA(char* prefix, size_t prefixlen,
WINPR_FORMAT_ARG const char* format, va_list args)
{
(void)vsnprintf(prefix, prefixlen, format, args);
}
WINPR_ATTR_FORMAT_ARG(3, 4)
static void WLog_PrintMessagePrefix(char* prefix, size_t prefixlen,
WINPR_FORMAT_ARG const char* format, ...)
{
va_list args = WINPR_C_ARRAY_INIT;
va_start(args, format);
WLog_PrintMessagePrefixVA(prefix, prefixlen, format, args);
va_end(args);
}
static const char* get_tid(void* arg)
{
struct format_tid_arg* targ = arg;
WINPR_ASSERT(targ);
size_t tid = 0;
#if defined __linux__ && !defined ANDROID
/* On Linux we prefer to see the LWP id */
tid = (size_t)syscall(SYS_gettid);
#else
tid = (size_t)GetCurrentThreadId();
#endif
(void)_snprintf(targ->tid, sizeof(targ->tid), "%08" PRIxz, tid);
return targ->tid;
}
static BOOL log_invalid_fmt(const char* what)
{
(void)fprintf(stderr, "Invalid format string '%s'\n", what);
return FALSE;
}
static BOOL check_and_log_format_size(char* format, size_t size, size_t index, size_t add)
{
/* format string must be '\0' terminated, so abort at size - 1 */
if (index + add + 1 >= size)
{
(void)fprintf(stderr,
"Format string too long ['%s', max %" PRIuz ", used %" PRIuz
", adding %" PRIuz "]\n",
format, size, index, add);
return FALSE;
}
return TRUE;
}
static int opt_compare_fn(const void* a, const void* b)
{
const char* what = a;
const struct format_option* opt = b;
if (!opt)
return -1;
return strncmp(what, opt->fmt, opt->fmtlen);
}
static BOOL replace_format_string(const char* FormatString, struct format_option_recurse* recurse,
char* format, size_t formatlen);
static const char* skip_if_null(const struct format_option* opt, const char* fmt,
size_t* preplacelen, size_t* pskiplen)
{
WINPR_ASSERT(opt);
WINPR_ASSERT(fmt);
WINPR_ASSERT(preplacelen);
WINPR_ASSERT(pskiplen);
*preplacelen = 0;
*pskiplen = 0;
const char* str = &fmt[opt->fmtlen]; /* Skip first %{ from string */
const char* end = strstr(str, opt->replace);
if (!end)
return nullptr;
*pskiplen = WINPR_ASSERTING_INT_CAST(size_t, end - fmt) + opt->replacelen;
if (!opt->arg.cpv)
return nullptr;
const size_t replacelen = WINPR_ASSERTING_INT_CAST(size_t, end - str);
char buffer[WLOG_MAX_PREFIX_SIZE] = WINPR_C_ARRAY_INIT;
memcpy(buffer, str, MIN(replacelen, ARRAYSIZE(buffer) - 1));
if (!replace_format_string(buffer, opt->recurse, opt->recurse->buffer,
ARRAYSIZE(opt->recurse->buffer)))
return nullptr;
*preplacelen = strnlen(opt->recurse->buffer, ARRAYSIZE(opt->recurse->buffer));
return opt->recurse->buffer;
}
static BOOL replace_format_string(const char* FormatString, struct format_option_recurse* recurse,
char* format, size_t formatlen)
{
WINPR_ASSERT(FormatString);
WINPR_ASSERT(recurse);
size_t index = 0;
while (*FormatString)
{
const struct format_option* opt =
bsearch(FormatString, recurse->options, recurse->nroptions,
sizeof(struct format_option), opt_compare_fn);
if (opt)
{
size_t replacelen = opt->replacelen;
size_t fmtlen = opt->fmtlen;
const char* replace = opt->replace;
const void* arg = opt->arg.cpv;
if (opt->ext)
replace = opt->ext(opt, FormatString, &replacelen, &fmtlen);
if (opt->fkt)
arg = opt->fkt(opt->arg.pv);
if (replace && (replacelen > 0))
{
WINPR_PRAGMA_DIAG_PUSH
WINPR_PRAGMA_DIAG_IGNORED_FORMAT_NONLITERAL
const int rc = _snprintf(&format[index], formatlen - index, replace, arg);
WINPR_PRAGMA_DIAG_POP
if (rc < 0)
return FALSE;
if (!check_and_log_format_size(format, formatlen, index,
WINPR_ASSERTING_INT_CAST(size_t, rc)))
return FALSE;
index += WINPR_ASSERTING_INT_CAST(size_t, rc);
}
FormatString += fmtlen;
}
else
{
/* Unknown format string */
if (*FormatString == '%')
return log_invalid_fmt(FormatString);
if (!check_and_log_format_size(format, formatlen, index, 1))
return FALSE;
format[index++] = *FormatString++;
}
}
return check_and_log_format_size(format, formatlen, index, 0);
}
BOOL WLog_Layout_GetMessagePrefix(wLog* log, wLogLayout* layout, const wLogMessage* message,
char* prefix, size_t prefixlen)
{
char format[WLOG_MAX_PREFIX_SIZE] = WINPR_C_ARRAY_INIT;
WINPR_ASSERT(layout);
WINPR_ASSERT(message);
WINPR_ASSERT(prefix);
struct format_tid_arg targ = WINPR_C_ARRAY_INIT;
SYSTEMTIME localTime = WINPR_C_ARRAY_INIT;
GetLocalTime(&localTime);
struct format_option_recurse recurse = {
.options = nullptr, .nroptions = 0, .log = log, .layout = layout, .message = message
};
#define ENTRY(x) x, sizeof(x) - 1
struct format_option options[] = {
{ ENTRY("%ctx"),
ENTRY("%s"),
log->custom,
{ .pv = log->context },
nullptr,
&recurse }, /* log context */
{ ENTRY("%dw"),
ENTRY("%u"),
nullptr,
{ .s = localTime.wDayOfWeek },
nullptr,
&recurse }, /* day of week */
{ ENTRY("%dy"),
ENTRY("%u"),
nullptr,
{ .s = localTime.wDay },
nullptr,
&recurse }, /* day of year
*/
{ ENTRY("%fl"),
ENTRY("%s"),
nullptr,
{ .cpv = message->FileName },
nullptr,
&recurse }, /* file
*/
{ ENTRY("%fn"),
ENTRY("%s"),
nullptr,
{ .cpv = message->FunctionName },
nullptr,
&recurse }, /* function
*/
{ ENTRY("%hr"),
ENTRY("%02u"),
nullptr,
{ .s = localTime.wHour },
nullptr,
&recurse }, /* hours
*/
{ ENTRY("%ln"),
ENTRY("%" PRIuz),
nullptr,
{ .s = message->LineNumber },
nullptr,
&recurse }, /* line number */
{ ENTRY("%lv"),
ENTRY("%s"),
nullptr,
{ .cpv = WLOG_LEVELS[message->Level] },
nullptr,
&recurse }, /* log level */
{ ENTRY("%mi"),
ENTRY("%02u"),
nullptr,
{ .s = localTime.wMinute },
nullptr,
&recurse }, /* minutes
*/
{ ENTRY("%ml"),
ENTRY("%03u"),
nullptr,
{ .s = localTime.wMilliseconds },
nullptr,
&recurse }, /* milliseconds */
{ ENTRY("%mn"), ENTRY("%s"), nullptr, { .cpv = log->Name }, nullptr, &recurse }, /* module
name */
{ ENTRY("%mo"),
ENTRY("%u"),
nullptr,
{ .s = localTime.wMonth },
nullptr,
&recurse }, /* month
*/
{ ENTRY("%pid"),
ENTRY("%u"),
nullptr,
{ .s = GetCurrentProcessId() },
nullptr,
&recurse }, /* process id */
{ ENTRY("%se"),
ENTRY("%02u"),
nullptr,
{ .s = localTime.wSecond },
nullptr,
&recurse }, /* seconds
*/
{ ENTRY("%tid"), ENTRY("%s"), get_tid, { .pv = &targ }, nullptr, &recurse }, /* thread id */
{ ENTRY("%yr"), ENTRY("%u"), nullptr, { .s = localTime.wYear }, nullptr, &recurse }, /* year
*/
{ ENTRY("%{"),
ENTRY("%}"),
nullptr,
{ .pv = log->context },
skip_if_null,
&recurse }, /* skip if no context */
};
recurse.options = options;
recurse.nroptions = ARRAYSIZE(options);
if (!replace_format_string(layout->FormatString, &recurse, format, ARRAYSIZE(format)))
return FALSE;
WINPR_PRAGMA_DIAG_PUSH
WINPR_PRAGMA_DIAG_IGNORED_FORMAT_SECURITY
WLog_PrintMessagePrefix(prefix, prefixlen, format);
WINPR_PRAGMA_DIAG_POP
return TRUE;
}
wLogLayout* WLog_GetLogLayout(wLog* log)
{
wLogAppender* appender = nullptr;
appender = WLog_GetLogAppender(log);
return appender->Layout;
}
BOOL WLog_Layout_SetPrefixFormat(WINPR_ATTR_UNUSED wLog* log, wLogLayout* layout,
const char* format)
{
free(layout->FormatString);
layout->FormatString = nullptr;
if (format)
{
layout->FormatString = _strdup(format);
if (!layout->FormatString)
return FALSE;
}
return TRUE;
}
wLogLayout* WLog_Layout_New(WINPR_ATTR_UNUSED wLog* log)
{
LPCSTR prefix = "WLOG_PREFIX";
DWORD nSize = 0;
char* env = nullptr;
wLogLayout* layout = nullptr;
layout = (wLogLayout*)calloc(1, sizeof(wLogLayout));
if (!layout)
return nullptr;
nSize = GetEnvironmentVariableA(prefix, nullptr, 0);
if (nSize)
{
env = (LPSTR)malloc(nSize);
if (!env)
{
free(layout);
return nullptr;
}
if (GetEnvironmentVariableA(prefix, env, nSize) != nSize - 1)
{
free(env);
free(layout);
return nullptr;
}
}
if (env)
layout->FormatString = env;
else
{
#ifdef ANDROID
layout->FormatString = _strdup("[pid=%pid:tid=%tid] - [%fn]%{[%ctx]%}: ");
#else
layout->FormatString =
_strdup("[%hr:%mi:%se:%ml] [%pid:%tid] [%lv][%mn] - [%fn]%{[%ctx]%}: ");
#endif
if (!layout->FormatString)
{
free(layout);
return nullptr;
}
}
return layout;
}
void WLog_Layout_Free(WINPR_ATTR_UNUSED wLog* log, wLogLayout* layout)
{
if (layout)
{
if (layout->FormatString)
{
free(layout->FormatString);
layout->FormatString = nullptr;
}
free(layout);
}
}

View File

@@ -0,0 +1,42 @@
/**
* WinPR: Windows Portable Runtime
* WinPR Logger
*
* Copyright 2013 Marc-Andre Moreau <marcandre.moreau@gmail.com>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef WINPR_WLOG_LAYOUT_PRIVATE_H
#define WINPR_WLOG_LAYOUT_PRIVATE_H
#include "wlog.h"
/**
* Log Layout
*/
struct s_wLogLayout
{
DWORD Type;
LPSTR FormatString;
};
WINPR_LOCAL void WLog_Layout_Free(wLog* log, wLogLayout* layout);
WINPR_ATTR_MALLOC(WLog_Layout_Free, 2)
WINPR_ATTR_NODISCARD
WINPR_LOCAL wLogLayout* WLog_Layout_New(wLog* log);
#endif /* WINPR_WLOG_LAYOUT_PRIVATE_H */

View File

@@ -0,0 +1,64 @@
/**
* WinPR: Windows Portable Runtime
* WinPR Logger
*
* Copyright 2013 Marc-Andre Moreau <marcandre.moreau@gmail.com>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <winpr/config.h>
#include <winpr/crt.h>
#include <winpr/path.h>
#include <winpr/file.h>
#include "wlog.h"
#include "Message.h"
char* WLog_Message_GetOutputFileName(int id, const char* ext)
{
DWORD ProcessId = 0;
char* FilePath = nullptr;
char* FileName = nullptr;
char* FullFileName = nullptr;
if (!(FileName = (char*)malloc(256)))
return nullptr;
FilePath = GetKnownSubPath(KNOWN_PATH_TEMP, "wlog");
if (!winpr_PathFileExists(FilePath))
{
if (!winpr_PathMakePath(FilePath, nullptr))
{
free(FileName);
free(FilePath);
return nullptr;
}
}
ProcessId = GetCurrentProcessId();
if (id >= 0)
(void)sprintf_s(FileName, 256, "%" PRIu32 "-%d.%s", ProcessId, id, ext);
else
(void)sprintf_s(FileName, 256, "%" PRIu32 ".%s", ProcessId, ext);
FullFileName = GetCombinedPath(FilePath, FileName);
free(FileName);
free(FilePath);
return FullFileName;
}

View File

@@ -0,0 +1,29 @@
/**
* WinPR: Windows Portable Runtime
* WinPR Logger
*
* Copyright 2013 Marc-Andre Moreau <marcandre.moreau@gmail.com>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef WINPR_WLOG_MESSAGE_PRIVATE_H
#define WINPR_WLOG_MESSAGE_PRIVATE_H
#include "DataMessage.h"
#include "ImageMessage.h"
#include "PacketMessage.h"
char* WLog_Message_GetOutputFileName(int id, const char* ext);
#endif /* WINPR_WLOG_MESSAGE_PRIVATE_H */

View File

@@ -0,0 +1,366 @@
/**
* WinPR: Windows Portable Runtime
* WinPR Logger
*
* Copyright 2013 Marc-Andre Moreau <marcandre.moreau@gmail.com>
* Copyright 2015 Thincast Technologies GmbH
* Copyright 2015 DI (FH) Martin Haimberger <martin.haimberger@thincast.com>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <winpr/config.h>
#include "wlog.h"
#include "PacketMessage.h"
#include <winpr/wtypes.h>
#include <winpr/crt.h>
#include <winpr/file.h>
#include <winpr/stream.h>
#include <winpr/sysinfo.h>
#include "../../log.h"
#define TAG WINPR_TAG("utils.wlog")
static BOOL Pcap_Read_Header(wPcap* pcap, wPcapHeader* header)
{
return (pcap && pcap->fp && fread((void*)header, sizeof(wPcapHeader), 1, pcap->fp) == 1);
}
static BOOL Pcap_Write_Header(wPcap* pcap, wPcapHeader* header)
{
return (pcap && pcap->fp && fwrite((void*)header, sizeof(wPcapHeader), 1, pcap->fp) == 1);
}
static BOOL Pcap_Write_RecordHeader(wPcap* pcap, wPcapRecordHeader* record)
{
return (pcap && pcap->fp && fwrite((void*)record, sizeof(wPcapRecordHeader), 1, pcap->fp) == 1);
}
static BOOL Pcap_Write_RecordContent(wPcap* pcap, wPcapRecord* record)
{
return (pcap && pcap->fp && fwrite(record->data, record->length, 1, pcap->fp) == 1);
}
static BOOL Pcap_Write_Record(wPcap* pcap, wPcapRecord* record)
{
return Pcap_Write_RecordHeader(pcap, &record->header) && Pcap_Write_RecordContent(pcap, record);
}
wPcap* Pcap_Open(char* name, BOOL write)
{
wPcap* pcap = nullptr;
FILE* pcap_fp = winpr_fopen(name, write ? "w+b" : "rb");
if (!pcap_fp)
{
WLog_ERR(TAG, "opening pcap file");
return nullptr;
}
pcap = (wPcap*)calloc(1, sizeof(wPcap));
if (!pcap)
goto out_fail;
pcap->name = name;
pcap->write = write;
pcap->record_count = 0;
pcap->fp = pcap_fp;
if (write)
{
pcap->header.magic_number = PCAP_MAGIC_NUMBER;
pcap->header.version_major = 2;
pcap->header.version_minor = 4;
pcap->header.thiszone = 0;
pcap->header.sigfigs = 0;
pcap->header.snaplen = 0xFFFFFFFF;
pcap->header.network = 1; /* ethernet */
if (!Pcap_Write_Header(pcap, &pcap->header))
goto out_fail;
}
else
{
if (_fseeki64(pcap->fp, 0, SEEK_END) < 0)
goto out_fail;
pcap->file_size = (SSIZE_T)_ftelli64(pcap->fp);
if (pcap->file_size < 0)
goto out_fail;
if (_fseeki64(pcap->fp, 0, SEEK_SET) < 0)
goto out_fail;
if (!Pcap_Read_Header(pcap, &pcap->header))
goto out_fail;
}
return pcap;
out_fail:
if (pcap_fp)
(void)fclose(pcap_fp);
free(pcap);
return nullptr;
}
void Pcap_Flush(wPcap* pcap)
{
if (!pcap || !pcap->fp)
return;
while (pcap->record)
{
if (!Pcap_Write_Record(pcap, pcap->record))
return;
pcap->record = pcap->record->next;
}
(void)fflush(pcap->fp);
}
void Pcap_Close(wPcap* pcap)
{
if (!pcap || !pcap->fp)
return;
Pcap_Flush(pcap);
(void)fclose(pcap->fp);
free(pcap);
}
static BOOL WLog_PacketMessage_Write_EthernetHeader(wPcap* pcap, wEthernetHeader* ethernet)
{
wStream* s = nullptr;
wStream sbuffer = WINPR_C_ARRAY_INIT;
BYTE buffer[14] = WINPR_C_ARRAY_INIT;
BOOL ret = TRUE;
if (!pcap || !pcap->fp || !ethernet)
return FALSE;
s = Stream_StaticInit(&sbuffer, buffer, sizeof(buffer));
if (!s)
return FALSE;
Stream_Write(s, ethernet->Destination, 6);
Stream_Write(s, ethernet->Source, 6);
Stream_Write_UINT16_BE(s, ethernet->Type);
if (fwrite(buffer, sizeof(buffer), 1, pcap->fp) != 1)
ret = FALSE;
return ret;
}
static UINT16 IPv4Checksum(const BYTE* ipv4, int length)
{
long checksum = 0;
while (length > 1)
{
const UINT16 tmp16 = *((const UINT16*)ipv4);
checksum += tmp16;
length -= 2;
ipv4 += 2;
}
if (length > 0)
checksum += *ipv4;
while (checksum >> 16)
checksum = (checksum & 0xFFFF) + (checksum >> 16);
return (UINT16)(~checksum);
}
static BOOL WLog_PacketMessage_Write_IPv4Header(wPcap* pcap, wIPv4Header* ipv4)
{
wStream* s = nullptr;
wStream sbuffer = WINPR_C_ARRAY_INIT;
BYTE buffer[20] = WINPR_C_ARRAY_INIT;
int ret = TRUE;
if (!pcap || !pcap->fp || !ipv4)
return FALSE;
s = Stream_StaticInit(&sbuffer, buffer, sizeof(buffer));
if (!s)
return FALSE;
Stream_Write_UINT8(s, (BYTE)((ipv4->Version << 4) | ipv4->InternetHeaderLength));
Stream_Write_UINT8(s, ipv4->TypeOfService);
Stream_Write_UINT16_BE(s, ipv4->TotalLength);
Stream_Write_UINT16_BE(s, ipv4->Identification);
Stream_Write_UINT16_BE(s, (UINT16)((ipv4->InternetProtocolFlags << 13) | ipv4->FragmentOffset));
Stream_Write_UINT8(s, ipv4->TimeToLive);
Stream_Write_UINT8(s, ipv4->Protocol);
Stream_Write_UINT16(s, ipv4->HeaderChecksum);
Stream_Write_UINT32_BE(s, ipv4->SourceAddress);
Stream_Write_UINT32_BE(s, ipv4->DestinationAddress);
ipv4->HeaderChecksum = IPv4Checksum((BYTE*)buffer, 20);
Stream_Rewind(s, 10);
Stream_Write_UINT16(s, ipv4->HeaderChecksum);
if (fwrite(buffer, sizeof(buffer), 1, pcap->fp) != 1)
ret = FALSE;
return ret;
}
static BOOL WLog_PacketMessage_Write_TcpHeader(wPcap* pcap, wTcpHeader* tcp)
{
wStream* s = nullptr;
wStream sbuffer = WINPR_C_ARRAY_INIT;
BYTE buffer[20] = WINPR_C_ARRAY_INIT;
BOOL ret = TRUE;
if (!pcap || !pcap->fp || !tcp)
return FALSE;
s = Stream_StaticInit(&sbuffer, buffer, sizeof(buffer));
if (!s)
return FALSE;
Stream_Write_UINT16_BE(s, tcp->SourcePort);
Stream_Write_UINT16_BE(s, tcp->DestinationPort);
Stream_Write_UINT32_BE(s, tcp->SequenceNumber);
Stream_Write_UINT32_BE(s, tcp->AcknowledgementNumber);
Stream_Write_UINT8(s, (UINT8)((tcp->Offset << 4) | (tcp->Reserved & 0xF)));
Stream_Write_UINT8(s, tcp->TcpFlags);
Stream_Write_UINT16_BE(s, tcp->Window);
Stream_Write_UINT16_BE(s, tcp->Checksum);
Stream_Write_UINT16_BE(s, tcp->UrgentPointer);
if (pcap->fp)
{
if (fwrite(buffer, sizeof(buffer), 1, pcap->fp) != 1)
ret = FALSE;
}
return ret;
}
static UINT32 g_InboundSequenceNumber = 0;
static UINT32 g_OutboundSequenceNumber = 0;
BOOL WLog_PacketMessage_Write(wPcap* pcap, void* data, size_t length, DWORD flags)
{
wTcpHeader tcp;
wIPv4Header ipv4;
wPcapRecord record;
wEthernetHeader ethernet;
ethernet.Type = 0x0800;
if (!pcap || !pcap->fp)
return FALSE;
if (flags & WLOG_PACKET_OUTBOUND)
{
/* 00:15:5D:01:64:04 */
ethernet.Source[0] = 0x00;
ethernet.Source[1] = 0x15;
ethernet.Source[2] = 0x5D;
ethernet.Source[3] = 0x01;
ethernet.Source[4] = 0x64;
ethernet.Source[5] = 0x04;
/* 00:15:5D:01:64:01 */
ethernet.Destination[0] = 0x00;
ethernet.Destination[1] = 0x15;
ethernet.Destination[2] = 0x5D;
ethernet.Destination[3] = 0x01;
ethernet.Destination[4] = 0x64;
ethernet.Destination[5] = 0x01;
}
else
{
/* 00:15:5D:01:64:01 */
ethernet.Source[0] = 0x00;
ethernet.Source[1] = 0x15;
ethernet.Source[2] = 0x5D;
ethernet.Source[3] = 0x01;
ethernet.Source[4] = 0x64;
ethernet.Source[5] = 0x01;
/* 00:15:5D:01:64:04 */
ethernet.Destination[0] = 0x00;
ethernet.Destination[1] = 0x15;
ethernet.Destination[2] = 0x5D;
ethernet.Destination[3] = 0x01;
ethernet.Destination[4] = 0x64;
ethernet.Destination[5] = 0x04;
}
ipv4.Version = 4;
ipv4.InternetHeaderLength = 5;
ipv4.TypeOfService = 0;
ipv4.TotalLength = (UINT16)(length + 20 + 20);
ipv4.Identification = 0;
ipv4.InternetProtocolFlags = 0x02;
ipv4.FragmentOffset = 0;
ipv4.TimeToLive = 128;
ipv4.Protocol = 6; /* TCP */
ipv4.HeaderChecksum = 0;
if (flags & WLOG_PACKET_OUTBOUND)
{
ipv4.SourceAddress = 0xC0A80196; /* 192.168.1.150 */
ipv4.DestinationAddress = 0x4A7D64C8; /* 74.125.100.200 */
}
else
{
ipv4.SourceAddress = 0x4A7D64C8; /* 74.125.100.200 */
ipv4.DestinationAddress = 0xC0A80196; /* 192.168.1.150 */
}
tcp.SourcePort = 3389;
tcp.DestinationPort = 3389;
if (flags & WLOG_PACKET_OUTBOUND)
{
tcp.SequenceNumber = g_OutboundSequenceNumber;
tcp.AcknowledgementNumber = g_InboundSequenceNumber;
WINPR_ASSERT(length + g_OutboundSequenceNumber <= UINT32_MAX);
g_OutboundSequenceNumber += WINPR_ASSERTING_INT_CAST(uint32_t, length);
}
else
{
tcp.SequenceNumber = g_InboundSequenceNumber;
tcp.AcknowledgementNumber = g_OutboundSequenceNumber;
WINPR_ASSERT(length + g_InboundSequenceNumber <= UINT32_MAX);
g_InboundSequenceNumber += WINPR_ASSERTING_INT_CAST(uint32_t, length);
}
tcp.Offset = 5;
tcp.Reserved = 0;
tcp.TcpFlags = 0x0018;
tcp.Window = 0x7FFF;
tcp.Checksum = 0;
tcp.UrgentPointer = 0;
record.data = data;
record.length = length;
const size_t offset = 14 + 20 + 20;
WINPR_ASSERT(record.length <= UINT32_MAX - offset);
const uint32_t rloff = WINPR_ASSERTING_INT_CAST(uint32_t, record.length + offset);
record.header.incl_len = rloff;
record.header.orig_len = rloff;
record.next = nullptr;
UINT64 ns = winpr_GetUnixTimeNS();
record.header.ts_sec = (UINT32)WINPR_TIME_NS_TO_S(ns);
record.header.ts_usec = WINPR_TIME_NS_REM_US(ns);
if (!Pcap_Write_RecordHeader(pcap, &record.header) ||
!WLog_PacketMessage_Write_EthernetHeader(pcap, &ethernet) ||
!WLog_PacketMessage_Write_IPv4Header(pcap, &ipv4) ||
!WLog_PacketMessage_Write_TcpHeader(pcap, &tcp) || !Pcap_Write_RecordContent(pcap, &record))
return FALSE;
(void)fflush(pcap->fp);
return TRUE;
}

View File

@@ -0,0 +1,111 @@
/**
* WinPR: Windows Portable Runtime
* WinPR Logger
*
* Copyright 2013 Marc-Andre Moreau <marcandre.moreau@gmail.com>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef WINPR_WLOG_PACKET_MESSAGE_PRIVATE_H
#define WINPR_WLOG_PACKET_MESSAGE_PRIVATE_H
#include "wlog.h"
#define PCAP_MAGIC_NUMBER 0xA1B2C3D4
typedef struct
{
UINT32 magic_number; /* magic number */
UINT16 version_major; /* major version number */
UINT16 version_minor; /* minor version number */
INT32 thiszone; /* GMT to local correction */
UINT32 sigfigs; /* accuracy of timestamps */
UINT32 snaplen; /* max length of captured packets, in octets */
UINT32 network; /* data link type */
} wPcapHeader;
typedef struct
{
UINT32 ts_sec; /* timestamp seconds */
UINT32 ts_usec; /* timestamp microseconds */
UINT32 incl_len; /* number of octets of packet saved in file */
UINT32 orig_len; /* actual length of packet */
} wPcapRecordHeader;
typedef struct s_wPcapRecort
{
wPcapRecordHeader header;
void* data;
size_t length;
struct s_wPcapRecort* next;
} wPcapRecord;
typedef struct
{
FILE* fp;
char* name;
BOOL write;
SSIZE_T file_size;
size_t record_count;
wPcapHeader header;
wPcapRecord* head;
wPcapRecord* tail;
wPcapRecord* record;
} wPcap;
wPcap* Pcap_Open(char* name, BOOL write);
void Pcap_Close(wPcap* pcap);
void Pcap_Flush(wPcap* pcap);
typedef struct
{
BYTE Destination[6];
BYTE Source[6];
UINT16 Type;
} wEthernetHeader;
typedef struct
{
BYTE Version;
BYTE InternetHeaderLength;
BYTE TypeOfService;
UINT16 TotalLength;
UINT16 Identification;
BYTE InternetProtocolFlags;
UINT16 FragmentOffset;
BYTE TimeToLive;
BYTE Protocol;
UINT16 HeaderChecksum;
UINT32 SourceAddress;
UINT32 DestinationAddress;
} wIPv4Header;
typedef struct
{
UINT16 SourcePort;
UINT16 DestinationPort;
UINT32 SequenceNumber;
UINT32 AcknowledgementNumber;
BYTE Offset;
BYTE Reserved;
BYTE TcpFlags;
UINT16 Window;
UINT16 Checksum;
UINT16 UrgentPointer;
} wTcpHeader;
BOOL WLog_PacketMessage_Write(wPcap* pcap, void* data, size_t length, DWORD flags);
#endif /* WINPR_WLOG_PACKET_MESSAGE_PRIVATE_H */

View File

@@ -0,0 +1,129 @@
/**
* WinPR: Windows Portable Runtime
* WinPR Logger
*
* Copyright © 2015 Thincast Technologies GmbH
* Copyright © 2015 David FORT <contact@hardening-consulting.com>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <winpr/config.h>
#include "SyslogAppender.h"
#include <syslog.h>
typedef struct
{
wLogAppender common;
} wLogSyslogAppender;
static int getSyslogLevel(DWORD level)
{
switch (level)
{
case WLOG_TRACE:
case WLOG_DEBUG:
return LOG_DEBUG;
case WLOG_INFO:
return LOG_INFO;
case WLOG_WARN:
return LOG_WARNING;
case WLOG_ERROR:
return LOG_ERR;
case WLOG_FATAL:
return LOG_CRIT;
case WLOG_OFF:
default:
return -1;
}
}
static BOOL WLog_SyslogAppender_Open(wLog* log, wLogAppender* appender)
{
return !(!log || !appender);
}
static BOOL WLog_SyslogAppender_Close(wLog* log, wLogAppender* appender)
{
return !(!log || !appender);
}
static BOOL WLog_SyslogAppender_WriteMessage(wLog* log, wLogAppender* appender,
const wLogMessage* message)
{
int syslogLevel = 0;
if (!log || !appender || !message)
return FALSE;
syslogLevel = getSyslogLevel(message->Level);
if (syslogLevel >= 0)
syslog(syslogLevel, "%s", message->TextString);
return TRUE;
}
static BOOL WLog_SyslogAppender_WriteDataMessage(wLog* log, wLogAppender* appender,
const wLogMessage* message)
{
int syslogLevel = 0;
if (!log || !appender || !message)
return FALSE;
syslogLevel = getSyslogLevel(message->Level);
if (syslogLevel >= 0)
syslog(syslogLevel, "skipped data message of %" PRIuz " bytes", message->Length);
return TRUE;
}
static BOOL WLog_SyslogAppender_WriteImageMessage(wLog* log, wLogAppender* appender,
const wLogMessage* message)
{
int syslogLevel = 0;
if (!log || !appender || !message)
return FALSE;
syslogLevel = getSyslogLevel(message->Level);
if (syslogLevel >= 0)
syslog(syslogLevel, "skipped image (%" PRIuz "x%" PRIuz "x%" PRIuz ")", message->ImageWidth,
message->ImageHeight, message->ImageBpp);
return TRUE;
}
static void WLog_SyslogAppender_Free(wLogAppender* appender)
{
free(appender);
}
wLogAppender* WLog_SyslogAppender_New(WINPR_ATTR_UNUSED wLog* log)
{
wLogSyslogAppender* appender = (wLogSyslogAppender*)calloc(1, sizeof(wLogSyslogAppender));
if (!appender)
return nullptr;
appender->common.Type = WLOG_APPENDER_SYSLOG;
appender->common.Open = WLog_SyslogAppender_Open;
appender->common.Close = WLog_SyslogAppender_Close;
appender->common.WriteMessage = WLog_SyslogAppender_WriteMessage;
appender->common.WriteDataMessage = WLog_SyslogAppender_WriteDataMessage;
appender->common.WriteImageMessage = WLog_SyslogAppender_WriteImageMessage;
appender->common.Free = WLog_SyslogAppender_Free;
return &appender->common;
}

View File

@@ -0,0 +1,33 @@
/**
* Copyright © 2015 Thincast Technologies GmbH
* Copyright © 2015 David FORT <contact@hardening-consulting.com>
*
* Permission to use, copy, modify, distribute, and sell this software and
* its documentation for any purpose is hereby granted without fee, provided
* that the above copyright notice appear in all copies and that both that
* copyright notice and this permission notice appear in supporting
* documentation, and that the name of the copyright holders not be used in
* advertising or publicity pertaining to distribution of the software
* without specific, written prior permission. The copyright holders make
* no representations about the suitability of this software for any
* purpose. It is provided "as is" without express or implied warranty.
*
* THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
* SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY
* SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
* RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
* CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#ifndef WINPR_LIBWINPR_UTILS_WLOG_SYSLOGAPPENDER_H_
#define WINPR_LIBWINPR_UTILS_WLOG_SYSLOGAPPENDER_H_
#include "wlog.h"
WINPR_ATTR_MALLOC(WLog_Appender_Free, 2)
WINPR_ATTR_NODISCARD
WINPR_LOCAL wLogAppender* WLog_SyslogAppender_New(wLog* log);
#endif /* WINPR_LIBWINPR_UTILS_WLOG_SYSLOGAPPENDER_H_ */

View File

@@ -0,0 +1,213 @@
/**
* WinPR: Windows Portable Runtime
* WinPR Logger
*
* Copyright © 2015 Thincast Technologies GmbH
* Copyright © 2015 David FORT <contact@hardening-consulting.com>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <winpr/config.h>
#include <winpr/crt.h>
#include <winpr/environment.h>
#include <winpr/winsock.h>
#include "wlog.h"
typedef struct
{
wLogAppender common;
char* host;
struct sockaddr targetAddr;
int targetAddrLen;
SOCKET sock;
} wLogUdpAppender;
static BOOL WLog_UdpAppender_Open(WINPR_ATTR_UNUSED wLog* log, wLogAppender* appender)
{
wLogUdpAppender* udpAppender = nullptr;
char addressString[256] = WINPR_C_ARRAY_INIT;
struct addrinfo hints = WINPR_C_ARRAY_INIT;
struct addrinfo* result = WINPR_C_ARRAY_INIT;
int status = 0;
char* colonPos = nullptr;
if (!appender)
return FALSE;
udpAppender = (wLogUdpAppender*)appender;
if (udpAppender->targetAddrLen) /* already opened */
return TRUE;
colonPos = strchr(udpAppender->host, ':');
if (!colonPos)
return FALSE;
const size_t addrLen = WINPR_ASSERTING_INT_CAST(size_t, (colonPos - udpAppender->host));
memcpy(addressString, udpAppender->host, addrLen);
addressString[addrLen] = '\0';
hints.ai_family = AF_INET;
hints.ai_socktype = SOCK_DGRAM;
status = getaddrinfo(addressString, colonPos + 1, &hints, &result);
if (status != 0)
return FALSE;
if (result->ai_addrlen > sizeof(udpAppender->targetAddr))
{
freeaddrinfo(result);
return FALSE;
}
memcpy(&udpAppender->targetAddr, result->ai_addr, result->ai_addrlen);
udpAppender->targetAddrLen = (int)result->ai_addrlen;
freeaddrinfo(result);
return TRUE;
}
static BOOL WLog_UdpAppender_Close(wLog* log, wLogAppender* appender)
{
return !(!log || !appender);
}
static BOOL WLog_UdpAppender_WriteMessage(wLog* log, wLogAppender* appender,
const wLogMessage* cmessage)
{
if (!log || !appender || !cmessage)
return FALSE;
wLogUdpAppender* udpAppender = (wLogUdpAppender*)appender;
char prefix[WLOG_MAX_PREFIX_SIZE] = WINPR_C_ARRAY_INIT;
WLog_Layout_GetMessagePrefix(log, appender->Layout, cmessage, prefix, sizeof(prefix));
(void)_sendto(udpAppender->sock, prefix, (int)strnlen(prefix, ARRAYSIZE(prefix)), 0,
&udpAppender->targetAddr, udpAppender->targetAddrLen);
(void)_sendto(udpAppender->sock, cmessage->TextString,
(int)strnlen(cmessage->TextString, INT_MAX), 0, &udpAppender->targetAddr,
udpAppender->targetAddrLen);
(void)_sendto(udpAppender->sock, "\n", 1, 0, &udpAppender->targetAddr,
udpAppender->targetAddrLen);
return TRUE;
}
static BOOL WLog_UdpAppender_WriteDataMessage(wLog* log, wLogAppender* appender,
const wLogMessage* message)
{
return !(!log || !appender || !message);
}
static BOOL WLog_UdpAppender_WriteImageMessage(wLog* log, wLogAppender* appender,
const wLogMessage* message)
{
return !(!log || !appender || !message);
}
static BOOL WLog_UdpAppender_Set(wLogAppender* appender, const char* setting, void* value)
{
const char target[] = "target";
wLogUdpAppender* udpAppender = (wLogUdpAppender*)appender;
/* Just check the value string is not empty */
if (!value || (strnlen(value, 2) == 0))
return FALSE;
if (strncmp(target, setting, sizeof(target)) != 0)
return FALSE;
udpAppender->targetAddrLen = 0;
if (udpAppender->host)
free(udpAppender->host);
udpAppender->host = _strdup((const char*)value);
return (udpAppender->host != nullptr) && WLog_UdpAppender_Open(nullptr, appender);
}
static void WLog_UdpAppender_Free(wLogAppender* appender)
{
wLogUdpAppender* udpAppender = nullptr;
if (appender)
{
udpAppender = (wLogUdpAppender*)appender;
if (udpAppender->sock != INVALID_SOCKET)
{
closesocket(udpAppender->sock);
udpAppender->sock = INVALID_SOCKET;
}
free(udpAppender->host);
free(udpAppender);
}
}
wLogAppender* WLog_UdpAppender_New(wLog* log)
{
DWORD nSize = 0;
LPCSTR name = nullptr;
wLogUdpAppender* appender = (wLogUdpAppender*)calloc(1, sizeof(wLogUdpAppender));
if (!appender)
return nullptr;
appender->common.Type = WLOG_APPENDER_UDP;
appender->common.Open = WLog_UdpAppender_Open;
appender->common.Close = WLog_UdpAppender_Close;
appender->common.WriteMessage = WLog_UdpAppender_WriteMessage;
appender->common.WriteDataMessage = WLog_UdpAppender_WriteDataMessage;
appender->common.WriteImageMessage = WLog_UdpAppender_WriteImageMessage;
appender->common.Free = WLog_UdpAppender_Free;
appender->common.Set = WLog_UdpAppender_Set;
appender->sock = _socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
if (appender->sock == INVALID_SOCKET)
goto error_sock;
name = "WLOG_UDP_TARGET";
nSize = GetEnvironmentVariableA(name, nullptr, 0);
if (nSize)
{
appender->host = (LPSTR)malloc(nSize);
if (!appender->host)
goto error_open;
if (GetEnvironmentVariableA(name, appender->host, nSize) != nSize - 1)
goto error_open;
if (!WLog_UdpAppender_Open(log, (wLogAppender*)appender))
goto error_open;
}
else
{
appender->host = _strdup("127.0.0.1:20000");
if (!appender->host)
goto error_open;
}
return &appender->common;
error_open:
free(appender->host);
closesocket(appender->sock);
error_sock:
free(appender);
return nullptr;
}

View File

@@ -0,0 +1,35 @@
/**
* Copyright © 2015 Thincast Technologies GmbH
* Copyright © 2015 David FORT <contact@hardening-consulting.com>
*
* Permission to use, copy, modify, distribute, and sell this software and
* its documentation for any purpose is hereby granted without fee, provided
* that the above copyright notice appear in all copies and that both that
* copyright notice and this permission notice appear in supporting
* documentation, and that the name of the copyright holders not be used in
* advertising or publicity pertaining to distribution of the software
* without specific, written prior permission. The copyright holders make
* no representations about the suitability of this software for any
* purpose. It is provided "as is" without express or implied warranty.
*
* THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
* SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY
* SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
* RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
* CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#ifndef WINPR_LIBWINPR_UTILS_WLOG_UDPAPPENDER_H_
#define WINPR_LIBWINPR_UTILS_WLOG_UDPAPPENDER_H_
#include <winpr/wlog.h>
#include "wlog.h"
WINPR_ATTR_MALLOC(WLog_Appender_Free, 2)
WINPR_ATTR_NODISCARD
WINPR_LOCAL wLogAppender* WLog_UdpAppender_New(wLog* log);
#endif /* WINPR_LIBWINPR_UTILS_WLOG_UDPAPPENDER_H_ */

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,90 @@
/**
* WinPR: Windows Portable Runtime
* WinPR Logger
*
* Copyright 2013 Marc-Andre Moreau <marcandre.moreau@gmail.com>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef WINPR_WLOG_PRIVATE_H
#define WINPR_WLOG_PRIVATE_H
#include <winpr/wlog.h>
#define WLOG_MAX_PREFIX_SIZE 512
typedef BOOL (*WLOG_APPENDER_OPEN_FN)(wLog* log, wLogAppender* appender);
typedef BOOL (*WLOG_APPENDER_CLOSE_FN)(wLog* log, wLogAppender* appender);
typedef BOOL (*WLOG_APPENDER_WRITE_MESSAGE_FN)(wLog* log, wLogAppender* appender,
const wLogMessage* message);
typedef BOOL (*WLOG_APPENDER_WRITE_DATA_MESSAGE_FN)(wLog* log, wLogAppender* appender,
const wLogMessage* message);
typedef BOOL (*WLOG_APPENDER_WRITE_IMAGE_MESSAGE_FN)(wLog* log, wLogAppender* appender,
const wLogMessage* message);
typedef BOOL (*WLOG_APPENDER_WRITE_PACKET_MESSAGE_FN)(wLog* log, wLogAppender* appender,
const wLogMessage* message);
typedef BOOL (*WLOG_APPENDER_SET)(wLogAppender* appender, const char* setting, void* value);
typedef void (*WLOG_APPENDER_FREE)(wLogAppender* appender);
struct s_wLogAppender
{
DWORD Type;
BOOL active;
wLogLayout* Layout;
CRITICAL_SECTION lock;
BOOL recursive;
void* TextMessageContext;
void* DataMessageContext;
void* ImageMessageContext;
void* PacketMessageContext;
WINPR_ATTR_NODISCARD WLOG_APPENDER_OPEN_FN Open;
WINPR_ATTR_NODISCARD WLOG_APPENDER_CLOSE_FN Close;
WINPR_ATTR_NODISCARD WLOG_APPENDER_WRITE_MESSAGE_FN WriteMessage;
WINPR_ATTR_NODISCARD WLOG_APPENDER_WRITE_DATA_MESSAGE_FN WriteDataMessage;
WINPR_ATTR_NODISCARD WLOG_APPENDER_WRITE_IMAGE_MESSAGE_FN WriteImageMessage;
WINPR_ATTR_NODISCARD WLOG_APPENDER_WRITE_PACKET_MESSAGE_FN WritePacketMessage;
WLOG_APPENDER_FREE Free;
WLOG_APPENDER_SET Set;
};
struct s_wLog
{
LPSTR Name;
LONG FilterLevel;
DWORD Level;
BOOL IsRoot;
BOOL inherit;
LPSTR* Names;
size_t NameCount;
wLogAppender* Appender;
wLog* Parent;
wLog** Children;
DWORD ChildrenCount;
DWORD ChildrenSize;
CRITICAL_SECTION lock;
WINPR_ATTR_NODISCARD const char* (*custom)(void*);
void* context;
};
WINPR_LOCAL extern const char* WLOG_LEVELS[7];
WINPR_LOCAL BOOL WLog_Layout_GetMessagePrefix(wLog* log, wLogLayout* layout,
const wLogMessage* message, char* prefix,
size_t prefixlen);
#include "Layout.h"
#include "Appender.h"
#endif /* WINPR_WLOG_PRIVATE_H */