The Battle for Wesnoth  1.19.0-dev
log_windows.cpp
Go to the documentation of this file.
1 /*
2  Copyright (C) 2014 - 2024
3  by Iris Morelle <shadowm2006@gmail.com>
4  Part of the Battle for Wesnoth Project https://www.wesnoth.org/
5 
6  This program is free software; you can redistribute it and/or modify
7  it under the terms of the GNU General Public License as published by
8  the Free Software Foundation; either version 2 of the License, or
9  (at your option) any later version.
10  This program is distributed in the hope that it will be useful,
11  but WITHOUT ANY WARRANTY.
12 
13  See the COPYING file for more details.
14 */
15 
16 // For some reason, it became necessary to include this before the header
17 // after switching to c++11
18 #include <cstdio>
19 
20 #include "log_windows.hpp"
21 
22 #include "filesystem.hpp"
23 #include "log.hpp"
25 
26 #include <ctime>
27 #include <iomanip>
28 #include <iostream>
29 
30 #include <boost/algorithm/string/predicate.hpp>
31 
32 #ifndef UNICODE
33 #define UNICODE
34 #endif
35 
36 #define WIN32_LEAN_AND_MEAN
37 
38 #include <windows.h>
39 
40 static lg::log_domain log_setup("logsetup");
41 #define ERR_LS LOG_STREAM(err, log_setup)
42 #define WRN_LS LOG_STREAM(warn, log_setup)
43 #define LOG_LS LOG_STREAM(info, log_setup)
44 #define DBG_LS LOG_STREAM(debug, log_setup)
45 
46 namespace lg
47 {
48 
49 namespace
50 {
51 /**
52  * Singleton class that handles sending logging output to a console on windows.
53  */
54 class console_handler
55 {
56 public:
57  console_handler(const console_handler&) = delete;
58  console_handler& operator=(const console_handler&) = delete;
59 
60  console_handler();
61 
62  /**
63  * Returns whether we own the console we are attached to, if any.
64  */
65  bool owns_console() const;
66 
67 private:
68  bool created_wincon_;
69 
70  /**
71  * Switches to using a native console.
72  */
73  void enable_native_console_output();
74 };
75 
76 console_handler::console_handler()
77  : created_wincon_(false)
78 {
79  DBG_LS << "Early init message";
80 
81  if(GetConsoleWindow() != nullptr) {
82  // Someone already attached a console to us. Assume we were compiled
83  // with the console subsystem flag and that the standard streams are
84  // already pointing to the console.
85  LOG_LS << "Console already attached at startup (built with console subsystem flag?), log file disabled.";
86  } else {
87  enable_native_console_output();
88  }
89 
90  DBG_LS << "Windows console init complete!";
91 }
92 
93 bool console_handler::owns_console() const
94 {
95  return created_wincon_;
96 }
97 
98 void console_handler::enable_native_console_output()
99 {
100  if(AttachConsole(ATTACH_PARENT_PROCESS)) {
101  LOG_LS << "Attached parent process console.";
102  } else if(AllocConsole()) {
103  LOG_LS << "Allocated own console.";
104  created_wincon_ = true;
105  } else {
106  // Wine as of version 4.21 just goes ERROR_ACCESS_DENIED when trying
107  // to allocate a console for a GUI subsystem application. We can ignore
108  // this since the user purportedly knows what they're doing and if they
109  // get radio silence from Wesnoth and no log files they'll realize that
110  // something went wrong.
111  WRN_LS << "Cannot attach or allocate a console, continuing anyway (is this Wine?)";
112  }
113 
114  DBG_LS << "stderr to console";
115  fflush(stderr);
116  std::cerr.flush();
117  assert(freopen("CONOUT$", "wb", stderr) == stderr);
118 
119  DBG_LS << "stdout to console";
120  fflush(stdout);
121  std::cout.flush();
122  assert(freopen("CONOUT$", "wb", stdout) == stdout);
123 
124  DBG_LS << "stdin from console";
125  assert(freopen("CONIN$", "rb", stdin) == stdin);
126 
127  LOG_LS << "Console streams handover complete!";
128 }
129 
130 std::unique_ptr<console_handler> lfm;
131 
132 } // end anonymous namespace
133 
135 {
136  if(!lfm) {
137  lfm.reset(new console_handler());
138  }
139 }
140 
142 {
143  return lfm && lfm->owns_console();
144 }
145 
146 } // end namespace lg
Declarations for File-IO.
Standard logging facilities (interface).
#define DBG_LS
Definition: log_windows.cpp:44
#define WRN_LS
Definition: log_windows.cpp:42
#define LOG_LS
Definition: log_windows.cpp:43
static lg::log_domain log_setup("logsetup")
Definition: pump.hpp:41
bool using_own_console()
Returns true if a console was allocated by the Wesnoth process.
void do_console_redirect()
Allocates a console if needed and redirects output to CONOUT.