E-MailRelay
glogoutput_win32.cpp
Go to the documentation of this file.
1//
2// Copyright (C) 2001-2024 Graeme Walker <graeme_walker@users.sourceforge.net>
3//
4// This program is free software: you can redistribute it and/or modify
5// it under the terms of the GNU General Public License as published by
6// the Free Software Foundation, either version 3 of the License, or
7// (at your option) any later version.
8//
9// This program is distributed in the hope that it will be useful,
10// but WITHOUT ANY WARRANTY; without even the implied warranty of
11// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12// GNU General Public License for more details.
13//
14// You should have received a copy of the GNU General Public License
15// along with this program. If not, see <http://www.gnu.org/licenses/>.
16// ===
17///
18/// \file glogoutput_win32.cpp
19///
20
21#include "gdef.h"
22#include "gnowide.h"
23#include "glogoutput.h"
24#include "gprocess.h"
25#include "gconvert.h"
26#include "genvironment.h"
27#include "gfile.h"
28#include <stdexcept>
29#include <fstream>
30
31namespace G
32{
33 namespace LogOutputWindowsImp
34 {
35 bool oldWindows() noexcept
36 {
37 return !IsWindowsVistaOrGreater() ;
38 }
39 }
40}
41
42void G::LogOutput::osoutput( int fd , Severity severity , char * message , std::size_t n )
43{
44 // event log
45 //
46 if( m_config.m_use_syslog &&
47 severity != Severity::Debug &&
48 severity != Severity::InfoVerbose &&
49 m_handle != HNULL )
50 {
51 DWORD id = 0x400003E9L ; // 1001
52 WORD type = EVENTLOG_INFORMATION_TYPE ;
53 if( severity == Severity::Warning )
54 {
55 id = 0x800003EAL ; // 1002
56 type = EVENTLOG_WARNING_TYPE ;
57 }
58 else if( severity == Severity::Error || severity == Severity::Assertion )
59 {
60 id = 0xC00003EBL ; // 1003
61 type = EVENTLOG_ERROR_TYPE ;
62 }
63
64 // very old windowses do not seem to recognise "!S!" format specifiers so
65 // as a workround (fwiw) use additional entries in messages.mc (1011, etc)
66 if( LogOutputWindowsImp::oldWindows() )
67 id += 10 ;
68
69 message[n] = '\0' ;
70 nowide::reportEvent( m_handle , id , type , message ) ;
71 }
72
73 // standard error or log file -- note that stderr is not accessible if a gui
74 // build -- stderr will be text mode whereas a log file will be binary
75 //
76 if( fd > 2 ) message[n++] = '\r' ;
77 message[n++] = '\n' ;
78 G::File::write( fd , message , n ) ;
79}
80
81void G::LogOutput::osinit()
82{
83 if( m_config.m_use_syslog )
84 {
85 Path this_exe = G::Process::exe() ;
86 if( !this_exe.empty() )
87 {
88 G::LogOutput::register_( this_exe ) ;
89
90 std::string this_name = this_exe.withoutExtension().basename() ;
91 m_handle = nowide::registerEventSource( this_name ) ;
92 if( m_handle == HNULL && !m_config.m_allow_bad_syslog )
93 throw EventLogError() ;
94 }
95 }
96}
97
98void G::LogOutput::register_( const Path & exe_path )
99{
100 // this method will normally fail because of access rights so it
101 // should also be run as part of the install process
102
103 std::string reg_path = std::string("SYSTEM/CurrentControlSet/services/eventlog/Application/")
104 .append( exe_path.withoutExtension().basename() ) ;
105
106 HKEY key = 0 ;
107 LONG e = nowide::regCreateKey( reg_path , &key ) ;
108 if( e == ERROR_SUCCESS && key != 0 )
109 {
110 DWORD types = EVENTLOG_INFORMATION_TYPE | EVENTLOG_WARNING_TYPE | EVENTLOG_ERROR_TYPE ;
111 nowide::regSetValue( key , "EventMessageFile" , exe_path.str() ) ;
112 nowide::regSetValue( key , "CategoryCount" , DWORD(1) ) ;
113 nowide::regSetValue( key , "CategoryMessageFile" , exe_path.str() ) ;
114 nowide::regSetValue( key , "TypesSupported" , types ) ;
115 }
116 if( key != 0 )
117 RegCloseKey( key ) ;
118}
119
120void G::LogOutput::oscleanup() const noexcept
121{
122 if( m_handle != HNULL )
123 DeregisterEventSource( m_handle ) ;
124}
125
static ssize_t write(int fd, const char *, std::size_t) noexcept
Calls ::write() or equivalent.
Definition: gfile_unix.cpp:154
static void register_(const Path &exe)
Registers the given executable as a source of logging.
int fd() const noexcept
Returns the output file descriptor.
Definition: glogoutput.cpp:127
static Path exe()
Returns the absolute path of the current executable, independent of the argv array passed to main().
Contains inline functions that convert to and from UTF-8 strings in order to call wide-character "W()...
Low-level classes.
Definition: garg.h:36