diff --git a/mfbt/Attributes.h b/mfbt/Attributes.h index dd7903aafdee..068321960a5b 100644 --- a/mfbt/Attributes.h +++ b/mfbt/Attributes.h @@ -868,9 +868,9 @@ #endif /* __cplusplus */ /** - * Printf style formats. MOZ_FORMAT_PRINTF can be used to annotate a - * function or method that is "printf-like"; this will let (some) - * compilers check that the arguments match the template string. + * Printf style formats. MOZ_FORMAT_PRINTF and MOZ_FORMAT_WPRINTF can be used + * to annotate a function or method that is "printf/wprintf-like"; this will let + * (some) compilers check that the arguments match the template string. * * This macro takes two arguments. The first argument is the argument * number of the template string. The second argument is the argument @@ -899,15 +899,33 @@ * on different platforms. The macro __MINGW_PRINTF_FORMAT maps to * either gnu_printf or ms_printf depending on where we are compiling * to avoid warnings on format specifiers that are legal. + * + * At time of writing MinGW has no wide equivalent to __MINGW_PRINTF_FORMAT; + * therefore __MINGW_WPRINTF_FORMAT has been implemented following the same + * pattern seen in MinGW's source. */ #ifdef __MINGW32__ # define MOZ_FORMAT_PRINTF(stringIndex, firstToCheck) \ __attribute__((format(__MINGW_PRINTF_FORMAT, stringIndex, firstToCheck))) +# ifndef __MINGW_WPRINTF_FORMAT +# if defined(__clang__) +# define __MINGW_WPRINTF_FORMAT wprintf +# elif defined(_UCRT) || __USE_MINGW_ANSI_STDIO +# define __MINGW_WPRINTF_FORMAT gnu_wprintf +# else +# define __MINGW_WPRINTF_FORMAT ms_wprintf +# endif +# endif +# define MOZ_FORMAT_WPRINTF(stringIndex, firstToCheck) \ + __attribute__((format(__MINGW_WPRINTF_FORMAT, stringIndex, firstToCheck))) #elif __GNUC__ || __clang__ # define MOZ_FORMAT_PRINTF(stringIndex, firstToCheck) \ __attribute__((format(printf, stringIndex, firstToCheck))) +# define MOZ_FORMAT_WPRINTF(stringIndex, firstToCheck) \ + __attribute__((format(wprintf, stringIndex, firstToCheck))) #else # define MOZ_FORMAT_PRINTF(stringIndex, firstToCheck) +# define MOZ_FORMAT_WPRINTF(stringIndex, firstToCheck) #endif /** diff --git a/toolkit/mozapps/defaultagent/EventLog.cpp b/toolkit/mozapps/defaultagent/EventLog.cpp index fac189c58290..eaac1161bbf4 100644 --- a/toolkit/mozapps/defaultagent/EventLog.cpp +++ b/toolkit/mozapps/defaultagent/EventLog.cpp @@ -6,65 +6,6 @@ #include "EventLog.h" -#include - -#include "mozilla/UniquePtr.h" - // This is an easy way to expose `MOZ_APP_DISPLAYNAME` to Rust code. const wchar_t* gWinEventLogSourceName = L"" MOZ_APP_DISPLAYNAME " Default Browser Agent"; - -static void WriteEventLogErrorBuffer(const wchar_t* buffer, DWORD eventId) { - HANDLE source = RegisterEventSourceW(nullptr, gWinEventLogSourceName); - if (!source) { - // Not much we can do about this. - return; - } - - const wchar_t* stringsArray[] = {buffer}; - ReportEventW(source, EVENTLOG_ERROR_TYPE, 0, eventId, nullptr, 1, 0, - stringsArray, nullptr); - - DeregisterEventSource(source); -} - -void WriteEventLogHresult(HRESULT hr, const char* sourceFile, int sourceLine) { - const wchar_t* format = L"0x%X in %S:%d"; - int bufferSize = _scwprintf(format, hr, sourceFile, sourceLine); - ++bufferSize; // Extra character for terminating null - mozilla::UniquePtr errorStr = - mozilla::MakeUnique(bufferSize); - - _snwprintf_s(errorStr.get(), bufferSize, _TRUNCATE, format, hr, sourceFile, - sourceLine); - - WriteEventLogErrorBuffer(errorStr.get(), hr); -} - -void WriteEventLogErrorMessage(const wchar_t* messageFormat, - const char* sourceFile, int sourceLine, ...) { - // First assemble the passed message - va_list ap; - va_start(ap, sourceLine); - int bufferSize = _vscwprintf(messageFormat, ap); - ++bufferSize; // Extra character for terminating null - va_end(ap); - mozilla::UniquePtr message = - mozilla::MakeUnique(bufferSize); - - va_start(ap, sourceLine); - vswprintf(message.get(), bufferSize, messageFormat, ap); - va_end(ap); - - // Next, assemble the complete error message to print - const wchar_t* errorFormat = L"Error: %s (%S:%d)"; - bufferSize = _scwprintf(errorFormat, message.get(), sourceFile, sourceLine); - ++bufferSize; // Extra character for terminating null - mozilla::UniquePtr errorStr = - mozilla::MakeUnique(bufferSize); - - _snwprintf_s(errorStr.get(), bufferSize, _TRUNCATE, errorFormat, - message.get(), sourceFile, sourceLine); - - WriteEventLogErrorBuffer(errorStr.get(), 0); -} diff --git a/toolkit/mozapps/defaultagent/EventLog.h b/toolkit/mozapps/defaultagent/EventLog.h index 8252e4d6feb3..672823266529 100644 --- a/toolkit/mozapps/defaultagent/EventLog.h +++ b/toolkit/mozapps/defaultagent/EventLog.h @@ -7,20 +7,16 @@ #ifndef __DEFAULT_BROWSER_AGENT_EVENT_LOG_H__ #define __DEFAULT_BROWSER_AGENT_EVENT_LOG_H__ -#include - MOZ_BEGIN_EXTERN_C extern MOZ_EXPORT const wchar_t* gWinEventLogSourceName; MOZ_END_EXTERN_C -void WriteEventLogHresult(HRESULT hr, const char* sourceFile, int sourceLine); -void WriteEventLogErrorMessage(const wchar_t* messageFormat, - const char* sourceFile, int sourceLine, ...); +#include "mozilla/WindowsEventLog.h" -#define LOG_ERROR(hr) WriteEventLogHresult(hr, __FUNCTION__, __LINE__) +#define LOG_ERROR(hr) MOZ_WIN_EVENT_LOG_ERROR(gWinEventLogSourceName, hr) #define LOG_ERROR_MESSAGE(format, ...) \ - WriteEventLogErrorMessage(format, __FUNCTION__, __LINE__, ##__VA_ARGS__) + MOZ_WIN_EVENT_LOG_ERROR_MESSAGE(gWinEventLogSourceName, format, __VA_ARGS__) #endif // __DEFAULT_BROWSER_AGENT_EVENT_LOG_H__ diff --git a/widget/windows/WindowsEventLog.h b/widget/windows/WindowsEventLog.h new file mode 100644 index 000000000000..39719a4611cf --- /dev/null +++ b/widget/windows/WindowsEventLog.h @@ -0,0 +1,98 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim:set ts=2 sw=2 sts=2 et cindent: */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#ifndef mozilla_WindowsEventLog_h +#define mozilla_WindowsEventLog_h + +/** + * Report messages to the Windows Event Log. + */ + +#include +#include + +#include "mozilla/Attributes.h" +#include "mozilla/UniquePtr.h" + +/** + * This header is intended for self-contained, header-only, utility code for + * Win32. It may be used outside of xul.dll, in places such as + * default-browser-agent.exe or notificationrouter.dll. If your code creates + * dependencies on Mozilla libraries, you should put it elsewhere. + */ + +#define MOZ_WIN_EVENT_LOG_ERROR(source, hr) \ + mozilla::WriteWindowsEventLogHresult(source, hr, __FUNCTION__, __LINE__) +#define MOZ_WIN_EVENT_LOG_ERROR_MESSAGE(source, format, ...) \ + mozilla::WriteWindowsEventLogErrorMessage(source, format, __FUNCTION__, \ + __LINE__, ##__VA_ARGS__) + +namespace mozilla { + +static void WriteWindowsEventLogErrorBuffer(const wchar_t* eventSourceName, + const wchar_t* buffer, + DWORD eventId) { + HANDLE source = RegisterEventSourceW(nullptr, eventSourceName); + if (!source) { + // Not much we can do about this. + return; + } + + const wchar_t* stringsArray[] = {buffer}; + ReportEventW(source, EVENTLOG_ERROR_TYPE, 0, eventId, nullptr, 1, 0, + stringsArray, nullptr); + + DeregisterEventSource(source); +} + +void WriteWindowsEventLogHresult(const wchar_t* eventSourceName, HRESULT hr, + const char* sourceFile, int sourceLine) { + const wchar_t* format = L"0x%X in %S:%d"; + int bufferSize = _scwprintf(format, hr, sourceFile, sourceLine); + ++bufferSize; // Extra character for terminating null + mozilla::UniquePtr errorStr = + mozilla::MakeUnique(bufferSize); + + _snwprintf_s(errorStr.get(), bufferSize, _TRUNCATE, format, hr, sourceFile, + sourceLine); + + WriteWindowsEventLogErrorBuffer(eventSourceName, errorStr.get(), hr); +} + +MOZ_FORMAT_WPRINTF(1, 4) +void WriteWindowsEventLogErrorMessage(const wchar_t* eventSourceName, + const wchar_t* messageFormat, + const char* sourceFile, int sourceLine, + ...) { + // First assemble the passed message + va_list ap; + va_start(ap, sourceLine); + int bufferSize = _vscwprintf(messageFormat, ap); + ++bufferSize; // Extra character for terminating null + va_end(ap); + mozilla::UniquePtr message = + mozilla::MakeUnique(bufferSize); + + va_start(ap, sourceLine); + vswprintf(message.get(), bufferSize, messageFormat, ap); + va_end(ap); + + // Next, assemble the complete error message to print + const wchar_t* errorFormat = L"Error: %s (%S:%d)"; + bufferSize = _scwprintf(errorFormat, message.get(), sourceFile, sourceLine); + ++bufferSize; // Extra character for terminating null + mozilla::UniquePtr errorStr = + mozilla::MakeUnique(bufferSize); + + _snwprintf_s(errorStr.get(), bufferSize, _TRUNCATE, errorFormat, + message.get(), sourceFile, sourceLine); + + WriteWindowsEventLogErrorBuffer(eventSourceName, errorStr.get(), 0); +} + +} // namespace mozilla + +#endif // mozilla_WindowsEventLog_h diff --git a/widget/windows/moz.build b/widget/windows/moz.build index 838382648318..eb3ad2db2280 100644 --- a/widget/windows/moz.build +++ b/widget/windows/moz.build @@ -38,6 +38,7 @@ EXPORTS.mozilla += [ "ShellHeaderOnlyUtils.h", "UrlmonHeaderOnlyUtils.h", "WindowsConsole.h", + "WindowsEventLog.h", "WinHeaderOnlyUtils.h", ]