From aaeb4ea0b2a25b2bd79b1e8be05f866e128b68b6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Moreau?= Date: Wed, 2 Oct 2013 15:41:46 -0400 Subject: [PATCH] libwinpr-utils: add wlog support for image and binary data --- winpr/include/winpr/wlog.h | 28 +++++-- winpr/libwinpr/utils/wlog/BinaryAppender.c | 18 ++++- winpr/libwinpr/utils/wlog/ConsoleAppender.c | 46 +++++++++++- winpr/libwinpr/utils/wlog/DataMessage.c | 18 +++++ winpr/libwinpr/utils/wlog/DataMessage.h | 2 +- winpr/libwinpr/utils/wlog/FileAppender.c | 43 ++++++++++- winpr/libwinpr/utils/wlog/ImageMessage.c | 83 +++++++++++++++++++++ winpr/libwinpr/utils/wlog/ImageMessage.h | 30 +++++++- winpr/libwinpr/utils/wlog/Message.c | 24 ++++++ winpr/libwinpr/utils/wlog/Message.h | 3 + winpr/libwinpr/utils/wlog/wlog.c | 68 ++++++++++++++++- 11 files changed, 348 insertions(+), 15 deletions(-) diff --git a/winpr/include/winpr/wlog.h b/winpr/include/winpr/wlog.h index a58bdfffd..56c775c53 100644 --- a/winpr/include/winpr/wlog.h +++ b/winpr/include/winpr/wlog.h @@ -50,8 +50,8 @@ typedef struct _wLogAppender wLogAppender; */ #define WLOG_MESSAGE_TEXT 0 -#define WLOG_MESSAGE_IMAGE 1 -#define WLOG_MESSAGE_DATA 2 +#define WLOG_MESSAGE_DATA 1 +#define WLOG_MESSAGE_IMAGE 2 struct _wLogMessage { @@ -67,6 +67,18 @@ struct _wLogMessage DWORD LineNumber; /* __LINE__ */ LPCSTR FileName; /* __FILE__ */ LPCSTR FunctionName; /* __FUNCTION__ */ + + /* Data Message */ + + void* Data; + int Length; + + /* Image Message */ + + void* ImageData; + int ImageWidth; + int ImageHeight; + int ImageBpp; }; /** @@ -91,6 +103,8 @@ struct _wLogLayout typedef int (*WLOG_APPENDER_OPEN_FN)(wLog* log, wLogAppender* appender); typedef int (*WLOG_APPENDER_CLOSE_FN)(wLog* log, wLogAppender* appender); typedef int (*WLOG_APPENDER_WRITE_MESSAGE_FN)(wLog* log, wLogAppender* appender, wLogMessage* message); +typedef int (*WLOG_APPENDER_WRITE_DATA_MESSAGE_FN)(wLog* log, wLogAppender* appender, wLogMessage* message); +typedef int (*WLOG_APPENDER_WRITE_IMAGE_MESSAGE_FN)(wLog* log, wLogAppender* appender, wLogMessage* message); #define WLOG_APPENDER_COMMON() \ DWORD Type; \ @@ -99,7 +113,9 @@ typedef int (*WLOG_APPENDER_WRITE_MESSAGE_FN)(wLog* log, wLogAppender* appender, CRITICAL_SECTION lock; \ WLOG_APPENDER_OPEN_FN Open; \ WLOG_APPENDER_CLOSE_FN Close; \ - WLOG_APPENDER_WRITE_MESSAGE_FN WriteMessage + WLOG_APPENDER_WRITE_MESSAGE_FN WriteMessage; \ + WLOG_APPENDER_WRITE_DATA_MESSAGE_FN WriteDataMessage; \ + WLOG_APPENDER_WRITE_IMAGE_MESSAGE_FN WriteImageMessage struct _wLogAppender { @@ -178,7 +194,7 @@ WINPR_API void WLog_PrintMessage(wLog* log, wLogMessage* message, ...); wLogMessage _log_message; \ _log_message.Type = WLOG_MESSAGE_IMAGE; \ _log_message.Level = _log_level; \ - _log_message.FormatString = _fmt; \ + _log_message.FormatString = NULL; \ _log_message.LineNumber = __LINE__; \ _log_message.FileName = __FILE__; \ _log_message.FunctionName = __FUNCTION__; \ @@ -188,9 +204,9 @@ WINPR_API void WLog_PrintMessage(wLog* log, wLogMessage* message, ...); #define WLog_Data(_log, _log_level, ...) \ if (_log_level <= _log->Level) { \ wLogMessage _log_message; \ - _log_message.Type = WLOG_MESSAGE_IMAGE; \ + _log_message.Type = WLOG_MESSAGE_DATA; \ _log_message.Level = _log_level; \ - _log_message.FormatString = _fmt; \ + _log_message.FormatString = NULL; \ _log_message.LineNumber = __LINE__; \ _log_message.FileName = __FILE__; \ _log_message.FunctionName = __FUNCTION__; \ diff --git a/winpr/libwinpr/utils/wlog/BinaryAppender.c b/winpr/libwinpr/utils/wlog/BinaryAppender.c index fbb153694..e9b8b4a97 100644 --- a/winpr/libwinpr/utils/wlog/BinaryAppender.c +++ b/winpr/libwinpr/utils/wlog/BinaryAppender.c @@ -131,6 +131,16 @@ int WLog_BinaryAppender_WriteMessage(wLog* log, wLogBinaryAppender* appender, wL return 1; } +int WLog_BinaryAppender_WriteDataMessage(wLog* log, wLogBinaryAppender* appender, wLogMessage* message) +{ + return 1; +} + +int WLog_BinaryAppender_WriteImageMessage(wLog* log, wLogBinaryAppender* appender, wLogMessage* message) +{ + return 1; +} + wLogBinaryAppender* WLog_BinaryAppender_New(wLog* log) { wLogBinaryAppender* BinaryAppender; @@ -143,7 +153,13 @@ wLogBinaryAppender* WLog_BinaryAppender_New(wLog* log) BinaryAppender->Open = (WLOG_APPENDER_OPEN_FN) WLog_BinaryAppender_Open; BinaryAppender->Close = (WLOG_APPENDER_OPEN_FN) WLog_BinaryAppender_Close; - BinaryAppender->WriteMessage = (WLOG_APPENDER_WRITE_MESSAGE_FN) WLog_BinaryAppender_WriteMessage; + + BinaryAppender->WriteMessage = + (WLOG_APPENDER_WRITE_MESSAGE_FN) WLog_BinaryAppender_WriteMessage; + BinaryAppender->WriteDataMessage = + (WLOG_APPENDER_WRITE_DATA_MESSAGE_FN) WLog_BinaryAppender_WriteDataMessage; + BinaryAppender->WriteImageMessage = + (WLOG_APPENDER_WRITE_IMAGE_MESSAGE_FN) WLog_BinaryAppender_WriteImageMessage; BinaryAppender->FileName = NULL; BinaryAppender->FilePath = NULL; diff --git a/winpr/libwinpr/utils/wlog/ConsoleAppender.c b/winpr/libwinpr/utils/wlog/ConsoleAppender.c index bc5f14dd8..0c70aa042 100644 --- a/winpr/libwinpr/utils/wlog/ConsoleAppender.c +++ b/winpr/libwinpr/utils/wlog/ConsoleAppender.c @@ -22,9 +22,12 @@ #endif #include +#include #include +#include "wlog/Message.h" + #include "wlog/ConsoleAppender.h" /** @@ -78,6 +81,41 @@ int WLog_ConsoleAppender_WriteMessage(wLog* log, wLogConsoleAppender* appender, return 1; } +static int g_DataId = 0; + +int WLog_ConsoleAppender_WriteDataMessage(wLog* log, wLogConsoleAppender* appender, wLogMessage* message) +{ + int DataId; + char* FullFileName; + + DataId = g_DataId++; + FullFileName = WLog_Message_GetOutputFileName(DataId, "dat"); + + WLog_DataMessage_Write(FullFileName, message->Data, message->Length); + + free(FullFileName); + + return DataId; +} + +static int g_ImageId = 0; + +int WLog_ConsoleAppender_WriteImageMessage(wLog* log, wLogConsoleAppender* appender, wLogMessage* message) +{ + int ImageId; + char* FullFileName; + + ImageId = g_ImageId++; + FullFileName = WLog_Message_GetOutputFileName(ImageId, "bmp"); + + WLog_ImageMessage_Write(FullFileName, message->ImageData, + message->ImageWidth, message->ImageHeight, message->ImageBpp); + + free(FullFileName); + + return ImageId; +} + wLogConsoleAppender* WLog_ConsoleAppender_New(wLog* log) { wLogConsoleAppender* ConsoleAppender; @@ -90,7 +128,13 @@ wLogConsoleAppender* WLog_ConsoleAppender_New(wLog* log) ConsoleAppender->Open = (WLOG_APPENDER_OPEN_FN) WLog_ConsoleAppender_Open; ConsoleAppender->Close = (WLOG_APPENDER_OPEN_FN) WLog_ConsoleAppender_Close; - ConsoleAppender->WriteMessage = (WLOG_APPENDER_WRITE_MESSAGE_FN) WLog_ConsoleAppender_WriteMessage; + + ConsoleAppender->WriteMessage = + (WLOG_APPENDER_WRITE_MESSAGE_FN) WLog_ConsoleAppender_WriteMessage; + ConsoleAppender->WriteDataMessage = + (WLOG_APPENDER_WRITE_DATA_MESSAGE_FN) WLog_ConsoleAppender_WriteDataMessage; + ConsoleAppender->WriteImageMessage = + (WLOG_APPENDER_WRITE_IMAGE_MESSAGE_FN) WLog_ConsoleAppender_WriteImageMessage; ConsoleAppender->outputStream = WLOG_CONSOLE_STDOUT; } diff --git a/winpr/libwinpr/utils/wlog/DataMessage.c b/winpr/libwinpr/utils/wlog/DataMessage.c index aeb80d24d..ded9f9af6 100644 --- a/winpr/libwinpr/utils/wlog/DataMessage.c +++ b/winpr/libwinpr/utils/wlog/DataMessage.c @@ -25,3 +25,21 @@ #include "wlog/DataMessage.h" +int WLog_DataMessage_Write(char* filename, void* data, int length) +{ + FILE* fp; + + fp = fopen(filename, "w+b"); + + if (!fp) + { + fprintf(stderr, "failed to open file %s\n", filename); + return -1; + } + + fwrite(data, length, 1, fp); + + fclose(fp); + + return 0; +} diff --git a/winpr/libwinpr/utils/wlog/DataMessage.h b/winpr/libwinpr/utils/wlog/DataMessage.h index e8e43ab65..bcfd917bd 100644 --- a/winpr/libwinpr/utils/wlog/DataMessage.h +++ b/winpr/libwinpr/utils/wlog/DataMessage.h @@ -24,6 +24,6 @@ #include "wlog/wlog.h" - +int WLog_DataMessage_Write(char* filename, void* data, int length); #endif /* WINPR_WLOG_DATA_MESSAGE_PRIVATE_H */ diff --git a/winpr/libwinpr/utils/wlog/FileAppender.c b/winpr/libwinpr/utils/wlog/FileAppender.c index d5af22dce..1498e36d6 100644 --- a/winpr/libwinpr/utils/wlog/FileAppender.c +++ b/winpr/libwinpr/utils/wlog/FileAppender.c @@ -131,6 +131,41 @@ int WLog_FileAppender_WriteMessage(wLog* log, wLogFileAppender* appender, wLogMe return 1; } +static int g_DataId = 0; + +int WLog_FileAppender_WriteDataMessage(wLog* log, wLogFileAppender* appender, wLogMessage* message) +{ + int DataId; + char* FullFileName; + + DataId = g_DataId++; + FullFileName = WLog_Message_GetOutputFileName(DataId, "dat"); + + WLog_DataMessage_Write(FullFileName, message->Data, message->Length); + + free(FullFileName); + + return DataId; +} + +static int g_ImageId = 0; + +int WLog_FileAppender_WriteImageMessage(wLog* log, wLogFileAppender* appender, wLogMessage* message) +{ + int ImageId; + char* FullFileName; + + ImageId = g_ImageId++; + FullFileName = WLog_Message_GetOutputFileName(ImageId, "bmp"); + + WLog_ImageMessage_Write(FullFileName, message->ImageData, + message->ImageWidth, message->ImageHeight, message->ImageBpp); + + free(FullFileName); + + return ImageId; +} + wLogFileAppender* WLog_FileAppender_New(wLog* log) { wLogFileAppender* FileAppender; @@ -143,7 +178,13 @@ wLogFileAppender* WLog_FileAppender_New(wLog* log) FileAppender->Open = (WLOG_APPENDER_OPEN_FN) WLog_FileAppender_Open; FileAppender->Close = (WLOG_APPENDER_OPEN_FN) WLog_FileAppender_Close; - FileAppender->WriteMessage = (WLOG_APPENDER_WRITE_MESSAGE_FN) WLog_FileAppender_WriteMessage; + + FileAppender->WriteMessage = + (WLOG_APPENDER_WRITE_MESSAGE_FN) WLog_FileAppender_WriteMessage; + FileAppender->WriteDataMessage = + (WLOG_APPENDER_WRITE_DATA_MESSAGE_FN) WLog_FileAppender_WriteDataMessage; + FileAppender->WriteImageMessage = + (WLOG_APPENDER_WRITE_IMAGE_MESSAGE_FN) WLog_FileAppender_WriteImageMessage; FileAppender->FileName = NULL; FileAppender->FilePath = NULL; diff --git a/winpr/libwinpr/utils/wlog/ImageMessage.c b/winpr/libwinpr/utils/wlog/ImageMessage.c index 54cda6d88..89af777c5 100644 --- a/winpr/libwinpr/utils/wlog/ImageMessage.c +++ b/winpr/libwinpr/utils/wlog/ImageMessage.c @@ -25,3 +25,86 @@ #include "wlog/ImageMessage.h" +#include +#include + +typedef struct +{ + BYTE magic[2]; +} BITMAP_MAGIC; + +typedef struct +{ + UINT32 filesz; + UINT16 creator1; + UINT16 creator2; + UINT32 bmp_offset; +} BITMAP_CORE_HEADER; + +typedef struct +{ + UINT32 header_sz; + INT32 width; + INT32 height; + UINT16 nplanes; + UINT16 bitspp; + UINT32 compress_type; + UINT32 bmp_bytesz; + INT32 hres; + INT32 vres; + UINT32 ncolors; + UINT32 nimpcolors; +} BITMAP_INFO_HEADER; + +int WLog_ImageMessage_Write(char* filename, void* data, int width, int height, int bpp) +{ + FILE* fp; + BITMAP_MAGIC magic; + BITMAP_CORE_HEADER header; + BITMAP_INFO_HEADER info_header; + + fp = fopen(filename, "w+b"); + + if (!fp) + { + fprintf(stderr, "failed to open file %s\n", filename); + return -1; + } + + magic.magic[0] = 'B'; + magic.magic[1] = 'M'; + + header.creator1 = 0; + header.creator2 = 0; + + header.bmp_offset = + sizeof(BITMAP_MAGIC) + + sizeof(BITMAP_CORE_HEADER) + + sizeof(BITMAP_INFO_HEADER); + + info_header.bmp_bytesz = width * height * (bpp / 8); + + header.filesz = + header.bmp_offset + + info_header.bmp_bytesz; + + info_header.width = width; + info_header.height = (-1) * height; + info_header.nplanes = 1; + info_header.bitspp = bpp; + info_header.compress_type = 0; + info_header.hres = width; + info_header.vres = height; + info_header.ncolors = 0; + info_header.nimpcolors = 0; + info_header.header_sz = sizeof(BITMAP_INFO_HEADER); + + fwrite((void*) &magic, sizeof(BITMAP_MAGIC), 1, fp); + fwrite((void*) &header, sizeof(BITMAP_CORE_HEADER), 1, fp); + fwrite((void*) &info_header, sizeof(BITMAP_INFO_HEADER), 1, fp); + fwrite((void*) data, info_header.bmp_bytesz, 1, fp); + + fclose(fp); + + return 0; +} diff --git a/winpr/libwinpr/utils/wlog/ImageMessage.h b/winpr/libwinpr/utils/wlog/ImageMessage.h index 8d1c8b69c..8046a008a 100644 --- a/winpr/libwinpr/utils/wlog/ImageMessage.h +++ b/winpr/libwinpr/utils/wlog/ImageMessage.h @@ -1 +1,29 @@ - +/** + * WinPR: Windows Portable Runtime + * WinPR Logger + * + * Copyright 2013 Marc-Andre Moreau + * + * 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 + +#include + +#include "wlog/wlog.h" + +int WLog_ImageMessage_Write(char* filename, void* data, int width, int height, int bpp); + +#endif /* WINPR_WLOG_IMAGE_MESSAGE_PRIVATE_H */ diff --git a/winpr/libwinpr/utils/wlog/Message.c b/winpr/libwinpr/utils/wlog/Message.c index f73a2dd9f..ac7605e7b 100644 --- a/winpr/libwinpr/utils/wlog/Message.c +++ b/winpr/libwinpr/utils/wlog/Message.c @@ -21,7 +21,31 @@ #include "config.h" #endif +#include +#include + #include #include "wlog/Message.h" +char* WLog_Message_GetOutputFileName(int id, const char* ext) +{ + DWORD ProcessId; + char* FilePath; + char* FileName; + char* FullFileName; + + ProcessId = GetCurrentProcessId(); + + FilePath = GetKnownSubPath(KNOWN_PATH_TEMP, "wlog"); + + FileName = (char*) malloc(256); + sprintf_s(FileName, 256, "%u-%d.%s", (unsigned int) ProcessId, id, ext); + + FullFileName = GetCombinedPath(FilePath, FileName); + + free(FileName); + free(FilePath); + + return FullFileName; +} diff --git a/winpr/libwinpr/utils/wlog/Message.h b/winpr/libwinpr/utils/wlog/Message.h index 251540b08..2c90216bd 100644 --- a/winpr/libwinpr/utils/wlog/Message.h +++ b/winpr/libwinpr/utils/wlog/Message.h @@ -24,6 +24,9 @@ #include "wlog/wlog.h" +#include "wlog/DataMessage.h" +#include "wlog/ImageMessage.h" +char* WLog_Message_GetOutputFileName(int id, const char* ext); #endif /* WINPR_WLOG_MESSAGE_PRIVATE_H */ diff --git a/winpr/libwinpr/utils/wlog/wlog.c b/winpr/libwinpr/utils/wlog/wlog.c index ac7481ce8..2eb0c4f09 100644 --- a/winpr/libwinpr/utils/wlog/wlog.c +++ b/winpr/libwinpr/utils/wlog/wlog.c @@ -75,14 +75,60 @@ int WLog_Write(wLog* log, wLogMessage* message) return status; } -void WLog_PrintMessageVA(wLog* log, wLogMessage* message, va_list args) +int WLog_WriteImage(wLog* log, wLogMessage* message) { + int status; + wLogAppender* appender; + + appender = WLog_GetLogAppender(log); + + if (!appender) + return -1; + + if (!appender->WriteImageMessage) + return -1; + + EnterCriticalSection(&appender->lock); + + status = appender->WriteImageMessage(log, appender, message); + + LeaveCriticalSection(&appender->lock); + + return status; +} + +int WLog_WriteData(wLog* log, wLogMessage* message) +{ + int status; + wLogAppender* appender; + + appender = WLog_GetLogAppender(log); + + if (!appender) + return -1; + + if (!appender->WriteDataMessage) + return -1; + + EnterCriticalSection(&appender->lock); + + status = appender->WriteDataMessage(log, appender, message); + + LeaveCriticalSection(&appender->lock); + + return status; +} + +int WLog_PrintMessageVA(wLog* log, wLogMessage* message, va_list args) +{ + int status = -1; + if (message->Type == WLOG_MESSAGE_TEXT) { if (!strchr(message->FormatString, '%')) { message->TextString = (LPSTR) message->FormatString; - WLog_Write(log, message); + status = WLog_Write(log, message); } else { @@ -90,24 +136,38 @@ void WLog_PrintMessageVA(wLog* log, wLogMessage* message, va_list args) wvsnprintfx(formattedLogMessage, WLOG_MAX_STRING_SIZE - 1, message->FormatString, args); message->TextString = formattedLogMessage; - WLog_Write(log, message); + status = WLog_Write(log, message); } } else if (message->Type == WLOG_MESSAGE_IMAGE) { + message->ImageData = va_arg(args, void*); + message->ImageWidth = va_arg(args, int); + message->ImageHeight = va_arg(args, int); + message->ImageBpp = va_arg(args, int); + status = WLog_WriteImage(log, message); } else if (message->Type == WLOG_MESSAGE_DATA) { + message->Data = va_arg(args, void*); + message->Length = va_arg(args, int); + status = WLog_WriteData(log, message); } + + return status; } void WLog_PrintMessage(wLog* log, wLogMessage* message, ...) { + int status; va_list args; + va_start(args, message); - WLog_PrintMessageVA(log, message, args); + + status = WLog_PrintMessageVA(log, message, args); + va_end(args); }