summaryrefslogtreecommitdiff
path: root/ACE/ace/Log_Msg_NT_Event_Log.cpp
blob: 29a8cd05afa6f15f6d278f708d5201e7fb17c99f (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
#include "ace/config-all.h"

#if defined (ACE_HAS_LOG_MSG_NT_EVENT_LOG)

#include "ace/Log_Msg_NT_Event_Log.h"
#include "ace/Log_Category.h"
#include "ace/Log_Record.h"
#include "ace/OS_NS_stdio.h"
#include "ace/OS_NS_string.h"

ACE_BEGIN_VERSIONED_NAMESPACE_DECL

ACE_Log_Msg_NT_Event_Log::ACE_Log_Msg_NT_Event_Log (void)
  : evlog_handle_(0)
{
}

ACE_Log_Msg_NT_Event_Log::~ACE_Log_Msg_NT_Event_Log (void)
{
  this->close ();
}

int
ACE_Log_Msg_NT_Event_Log::open (const ACE_TCHAR *logger_key)
{
  // ACE's "resource module" contains the message resource required
  // for event logging.
  ACE_TCHAR msg_file [MAXPATHLEN];

  if (!ACE_TEXT_GetModuleFileName (ACE_OS::get_win32_resource_module (),
                                   msg_file,
                                   MAXPATHLEN))
    return -1;
  DWORD msg_file_length =
    static_cast<DWORD> ((ACE_OS::strlen (msg_file) + 1) * sizeof (ACE_TCHAR));

  // If a logger_key has been supplied then we use that as the event
  // source name, otherwise we default to the program name.
  const ACE_TCHAR *event_source_name = logger_key ? logger_key : ACE_Log_Msg::program_name ();

  // Information is stored in the registry at a location based on the
  // program name.
  ACE_TCHAR reg_key [MAXPATHLEN];
  ACE_OS::strcpy (reg_key,
                  ACE_TEXT ("SYSTEM\\CurrentControlSet\\Services\\EventLog\\Application\\"));
  size_t reg_key_length = ACE_OS::strlen(reg_key);
  ACE_OS::strncat (reg_key,
                   event_source_name,
                   MAXPATHLEN - reg_key_length);

  // Add the event source to the registry. Note that if this fails it
  // is not fatal. The application will still be able to write entries
  // to the event log, they just won't be formatted correctly.
  HKEY hkey;
  ACE_TEXT_RegCreateKey (HKEY_LOCAL_MACHINE,
                         reg_key,
                         &hkey);
  DWORD flags = EVENTLOG_ERROR_TYPE | EVENTLOG_WARNING_TYPE | EVENTLOG_INFORMATION_TYPE;
  ACE_TEXT_RegSetValueEx (hkey,
                          ACE_TEXT ("TypesSupported"),
                          0,
                          REG_DWORD,
                          (LPBYTE) &flags,
                          sizeof (DWORD));
  ACE_TEXT_RegSetValueEx (hkey,
                          ACE_TEXT ("EventMessageFile"),
                          0,
                          REG_SZ,
                          (LPBYTE) msg_file,
                          msg_file_length);
  RegCloseKey (hkey);

  // Obtain a handle to the event source.
  this->evlog_handle_ = ACE_TEXT_RegisterEventSource (0,
                                                      event_source_name);
  return this->evlog_handle_ ? 0 : -1;
}

int
ACE_Log_Msg_NT_Event_Log::reset (void)
{
  return this->close ();
}

int
ACE_Log_Msg_NT_Event_Log::close (void)
{
  if (this->evlog_handle_ == 0
      || DeregisterEventSource (this->evlog_handle_))
    {
      this->evlog_handle_ = 0;
      return 0;
    }
  else
    return -1;
}

ssize_t
ACE_Log_Msg_NT_Event_Log::log (ACE_Log_Record &log_record)
{
  // Make a copy of the log text and replace any newlines with
  // CR-LF. Newline characters on their own do not appear correctly in
  // the event viewer. We allow for a doubling in the size of the msg
  // data for the worst case of all newlines.
  const ACE_TCHAR *src_msg_data = log_record.msg_data ();
  ACE_TCHAR msg_data [(ACE_Log_Record::MAXLOGMSGLEN * 2) + 1];

  size_t maxlen = ACE_Log_Record::MAXLOGMSGLEN;
  if (ACE_Log_Record::MAXLOGMSGLEN > log_record.msg_data_len ())
    maxlen = log_record.msg_data_len ();

  size_t end = 0;
  for (size_t i = 0, j = 0;
       i < maxlen;
       ++i)
    {
      if (src_msg_data[i] == '\n')
        {
          msg_data[j++] = '\r';
          msg_data[j++] = '\n';
        }
      else
        msg_data[j++] = src_msg_data[i];

      end = j;
    }
  msg_data[end] = '\0';

  // Map the ACE log record type to an event log type.
  WORD event_type;
  switch (log_record.type ())
  {
  case LM_STARTUP:
  case LM_SHUTDOWN:
  case LM_TRACE:
  case LM_DEBUG:
  case LM_INFO:
    event_type = EVENTLOG_INFORMATION_TYPE;
    break;
  case LM_NOTICE:
  case LM_WARNING:
    event_type = EVENTLOG_WARNING_TYPE;
    break;
  case LM_ERROR:
  case LM_CRITICAL:
  case LM_ALERT:
  case LM_EMERGENCY:
  default:
    event_type = EVENTLOG_ERROR_TYPE;
    break;
  }

  // Send the log message to the system event log.
  const ACE_TCHAR* msgs [1];
  msgs[0] = msg_data;

  if (ACE_TEXT_ReportEvent (this->evlog_handle_,
                            event_type, 0, 0, 0, 1, 0, msgs, 0) == 0)
    return -1;
  else
    return 0;
}

ACE_END_VERSIONED_NAMESPACE_DECL

#endif /* ACE_HAS_LOG_MSG_NT_EVENT_LOG */