view common/logging.c @ 620:bc02ee484067

Add dummy logging with ressourced messages. The hack in icon.rc is necessary as with mingw 3.0 there appears to be a problem to include multiple resources after another. The data is included but the sections are not detected correctly in windows. Combining them in a single resource fixes this.
author Andre Heinecke <andre.heinecke@intevation.de>
date Thu, 19 Jun 2014 17:48:10 +0200
parents 0172740f5c6e
children 5042ace08cba
line wrap: on
line source
/* Copyright (C) 2014 by Bundesamt für Sicherheit in der Informationstechnik
 * Software engineering by Intevation GmbH
 *
 * This file is Free Software under the GNU GPL (v>=2)
 * and comes with ABSOLUTELY NO WARRANTY!
 * See LICENSE.txt for details.
 */
#include "logging.h"
#include "strhelp.h"

#include <stdio.h>
#include <stdarg.h>
#include <stdbool.h>

#include <strhelp.h>

#ifdef WIN32
# include <windows.h>
# include "events.h"
#else
# include <syslog.h>
#endif


#ifdef WIN32
static void
win_log(const char *format, va_list ap, bool error)
{
  HANDLE log_src = NULL,
         process_token = NULL;
  wchar_t *wmsg = NULL;
  BOOL success = FALSE;
  char buffer[MAX_LOG+1];
  PTOKEN_USER user_struct = NULL;
  PSID user_sid = NULL;

  vsnprintf (buffer, MAX_LOG, format, ap);
  buffer[MAX_LOG] = '\0';

  log_src = RegisterEventSourceW (NULL, L"" LOG_NAME);

  if (log_src == NULL)
    {
      PRINTLASTERROR ("Failed to open log source.");
      return;
    }

  wmsg = utf8_to_wchar (buffer, strlen(buffer));
  if (wmsg == NULL)
    {
      ERRORPRINTF ("Failed to convert log message to utf-16");
      goto done;
    }

  /* Get the current user sid for logging */

  OpenProcessToken (GetCurrentProcess(), TOKEN_READ, &process_token);
  if (process_token)
    {
      DWORD size = 0;

      // check how much space is needed
      GetTokenInformation (process_token, TokenUser, NULL, 0, &size);
      if (ERROR_INSUFFICIENT_BUFFER == GetLastError())
        {
          user_struct = xmalloc (size);
          GetTokenInformation (process_token, TokenUser, user_struct, size, &size);
          user_sid = user_struct->User.Sid;
        }
    }


  success = ReportEventW (log_src,
                          error ? EVENTLOG_ERROR_TYPE : EVENTLOG_INFORMATION_TYPE,
                          EVENT_CAT_TB,
                          error ? MSG_DEFAULT_ERROR : MSG_DEFAULT_INFO,
                          user_sid,
                          1,
                          0,
                          (const WCHAR **) &wmsg,
                          NULL);
  if (!success)
    {
      PRINTLASTERROR ("Failed to report event.");
    }

done:
  if (process_token)
    {
      CloseHandle(process_token);
    }
  xfree (user_struct);
  xfree (wmsg);

  if (!DeregisterEventSource (log_src))
    {
      PRINTLASTERROR ("Failed to close log source.");
    }
  return;
}

char *
getLastErrorMsg()
{
  LPWSTR bufPtr = NULL;
  DWORD err = GetLastError();
  char *retval = NULL;
  FormatMessageW (FORMAT_MESSAGE_ALLOCATE_BUFFER |
                  FORMAT_MESSAGE_FROM_SYSTEM |
                  FORMAT_MESSAGE_IGNORE_INSERTS,
                  NULL, err, 0, (LPWSTR) &bufPtr, 0, NULL);
  if (!bufPtr)
    {
      HMODULE hWinhttp = GetModuleHandleW (L"crypt32");
      if (hWinhttp)
        {
          FormatMessageW (FORMAT_MESSAGE_ALLOCATE_BUFFER |
                          FORMAT_MESSAGE_FROM_HMODULE |
                          FORMAT_MESSAGE_IGNORE_INSERTS,
                          hWinhttp, HRESULT_CODE (err), 0,
                          (LPWSTR) &bufPtr, 0, NULL);
        }
    }
  if (!bufPtr) {
    fprintf (stderr, "Error getting last error for code: %lx \n", err);
    return NULL;
  }

  retval = wchar_to_utf8(bufPtr, wcslen(bufPtr));
  LocalFree (bufPtr);

  return retval;
}

#else /* WIN32 */


static void
linux_log (const char *format, va_list ap, bool error)
{
  openlog (LOG_NAME, LOG_CONS | LOG_PID | LOG_NDELAY, LOG_USER);
  vsyslog ( error ? LOG_ERR : LOG_INFO, format, ap);
}

#endif /* WIN32 */

void
syslog_info_printf(const char *format, ...)
{
  va_list args;
  va_start (args, format);
#ifdef WIN32
  win_log (format, args, false);
#else
  linux_log (format, args, false);
#endif
  va_end (args);
}

void
syslog_error_printf(const char *format, ...)
{
  va_list args;
  va_start (args, format);
#ifdef WIN32
  win_log (format, args, true);
#else
  linux_log (format, args, true);
#endif
  va_end (args);
}

http://wald.intevation.org/projects/trustbridge/