Azure IoT common library
Fork of azure_c_shared_utility by
Diff: consolelogger.c
- Revision:
- 27:8656a313842b
- Parent:
- 25:8507bf644fdf
--- a/consolelogger.c Mon May 08 10:51:21 2017 -0700 +++ b/consolelogger.c Mon May 22 10:35:55 2017 -0700 @@ -7,15 +7,204 @@ #include "azure_c_shared_utility/xlogging.h" #include "azure_c_shared_utility/consolelogger.h" +#if (defined(_MSC_VER)) && (!(defined WINCE)) +#include "windows.h" + +/*returns a string as if printed by vprintf*/ +static char* vprintf_alloc(const char* format, va_list va) +{ + char* result; + int neededSize = vsnprintf(NULL, 0, format, va); + if (neededSize < 0) + { + result = NULL; + } + else + { + result = (char*)malloc(neededSize + 1); + if (result == NULL) + { + /*return as is*/ + } + else + { + if (vsnprintf(result, neededSize + 1, format, va) != neededSize) + { + free(result); + result = NULL; + } + } + } + return result; +} + +/*returns a string as if printed by printf*/ +static char* printf_alloc(const char* format, ...) +{ + char* result; + va_list va; + va_start(va, format); + result = vprintf_alloc(format, va); + va_end(va); + return result; +} + +/*returns NULL if it fails*/ +static char* lastErrorToString(DWORD lastError) +{ + char* result; + if (lastError == 0) + { + result = printf_alloc(""); /*no error should appear*/ + if (result == NULL) + { + (void)printf("failure in printf_alloc"); + } + else + { + /*return as is*/ + } + } + else + { + char temp[MESSAGE_BUFFER_SIZE]; + if (FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, lastError, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), temp, MESSAGE_BUFFER_SIZE, NULL) == 0) + { + result = printf_alloc("GetLastError()=0X%x", lastError); + if (result == NULL) + { + (void)printf("failure in printf_alloc\n"); + /*return as is*/ + } + else + { + /*return as is*/ + } + } + else + { + /*eliminate the \r or \n from the string*/ + /*one replace of each is enough*/ + char* whereAreThey; + if ((whereAreThey = strchr(temp, '\r')) != NULL) + { + *whereAreThey = '\0'; + } + if ((whereAreThey = strchr(temp, '\n')) != NULL) + { + *whereAreThey = '\0'; + } + + result = printf_alloc("GetLastError()==0X%x (%s)", lastError, temp); + + if (result == NULL) + { + (void)printf("failure in printf_alloc\n"); + /*return as is*/ + } + else + { + /*return as is*/ + } + } + } + return result; +} +/*this function will use 1x printf (in the happy case) .*/ +/*more than 1x printf / function call can mean intermingled LogErrors in a multithreaded env*/ +/*the function will also attempt to produce some human readable strings for GetLastError*/ +void consolelogger_log_with_GetLastError(const char* file, const char* func, int line, const char* format, ...) +{ + DWORD lastError; + char* lastErrorAsString; + int lastErrorAsString_should_be_freed; + time_t t; + int systemMessage_should_be_freed; + char* systemMessage; + int userMessage_should_be_freed; + char* userMessage; + + va_list args; + va_start(args, format); + + /*this is what this case will do: + 1. snip the last error + 2. create a string with what that last error means + 3. printf the system message (__FILE__, __LINE__ etc) + the last error + whatever the user wanted + */ + /*1. snip the last error*/ + lastError = GetLastError(); + + /*2. create a string with what that last error means*/ + lastErrorAsString = lastErrorToString(lastError); + if (lastErrorAsString == NULL) + { + (void)printf("failure in lastErrorToString"); + lastErrorAsString = ""; + lastErrorAsString_should_be_freed = 0; + } + else + { + lastErrorAsString_should_be_freed = 1; + } + + t = time(NULL); + systemMessage = printf_alloc("Error: Time:%.24s File:%s Func:%s Line:%d %s", ctime(&t), file, func, line, lastErrorAsString); + + if (systemMessage == NULL) + { + systemMessage = ""; + (void)printf("Error: [FAILED] Time:%.24s File : %s Func : %s Line : %d %s", ctime(&t), file, func, line, lastErrorAsString); + systemMessage_should_be_freed = 0; + } + else + { + systemMessage_should_be_freed = 1; + } + + userMessage = vprintf_alloc(format, args); + if (userMessage == NULL) + { + (void)printf("[FAILED] "); + (void)vprintf(format, args); + (void)printf("\n"); + userMessage_should_be_freed = 0; + } + else + { + /*3. printf the system message(__FILE__, __LINE__ etc) + the last error + whatever the user wanted*/ + (void)printf("%s %s\n", systemMessage, userMessage); + userMessage_should_be_freed = 1; + } + + if (userMessage_should_be_freed == 1) + { + free(userMessage); + } + + if (systemMessage_should_be_freed == 1) + { + free(systemMessage); + } + + if (lastErrorAsString_should_be_freed == 1) + { + free(lastErrorAsString); + } + va_end(args); +} +#endif + #if defined(__GNUC__) __attribute__ ((format (printf, 6, 7))) #endif -void consolelogger_log(LOG_CATEGORY log_category, const char* file, const char* func, const int line, unsigned int options, const char* format, ...) +void consolelogger_log(LOG_CATEGORY log_category, const char* file, const char* func, int line, unsigned int options, const char* format, ...) { + time_t t; va_list args; va_start(args, format); - time_t t = time(NULL); + t = time(NULL); switch (log_category) { @@ -29,12 +218,13 @@ break; } - (void)vprintf(format, args); - va_end(args); + (void)vprintf(format, args); + va_end(args); (void)log_category; - if (options & LOG_LINE) - { - (void)printf("\r\n"); - } + if (options & LOG_LINE) + { + (void)printf("\r\n"); + } } +