[SDK][CRT][MSVCRT] Implement _CrtSetReportMode and _CrtSetReportFile (#5662)

- Implement reporting to file.
CORE-11835, CORE-15517, ROSTESTS-386
This commit is contained in:
Katayama Hirofumi MZ 2023-09-11 04:37:27 +09:00 committed by GitHub
parent 993a45024e
commit 85377ee3db
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 64 additions and 14 deletions

View file

@ -199,9 +199,9 @@
@ cdecl -arch=i386 _CItanh()
@ stub -version=0x600+ _CrtCheckMemory
@ stub -version=0x600+ _CrtDbgBreak
@ stub -version=0x600+ _CrtDbgReport
@ cdecl -version=0x600+ _CrtDbgReport(long str long str str)
@ stub -version=0x600+ _CrtDbgReportV
@ stub -version=0x600+ _CrtDbgReportW
@ cdecl -version=0x600+ _CrtDbgReportW(long wstr long wstr wstr)
@ stub -version=0x600+ _CrtDbgReportWV
@ stub -version=0x600+ _CrtDoForAllClientObjects
@ stub -version=0x600+ _CrtDumpMemoryLeaks
@ -218,10 +218,10 @@
@ stub -version=0x600+ _CrtSetDbgBlockType
@ stub -version=0x600+ _CrtSetDbgFlag
@ stub -version=0x600+ _CrtSetDumpClient
@ stub -version=0x600+ _CrtSetReportFile
@ cdecl -version=0x600+ _CrtSetReportFile(long ptr)
@ stub -version=0x600+ _CrtSetReportHook
@ stub -version=0x600+ _CrtSetReportHook2
@ stub -version=0x600+ _CrtSetReportMode
@ cdecl -version=0x600+ _CrtSetReportMode(long long)
@ stdcall _CxxThrowException(long long)
@ cdecl -arch=i386 -norelay _EH_prolog()
@ cdecl _Getdays()

View file

@ -91,8 +91,6 @@ extern "C" {
#endif
// Assertion and error reporting
#ifndef _DEBUG
@ -124,6 +122,8 @@ extern "C" {
#define _RPTFW0(rptno,msg)
#define _RPTFWN(rptno,msg,...)
#define _CrtSetReportMode(t,f) ((int)0)
#define _CrtSetReportFile(t,f) ((_HFILE)0)
#else // _DEBUG
@ -161,6 +161,9 @@ extern "C" {
#define _RPTFW0(rptno,msg) _RPT_BASEW(rptno, _CRT_WIDE(__FILE__), __LINE__, NULL, L"%s", msg)
#define _RPTFWN(rptno,msg,...) _RPT_BASEW(rptno, _CRT_WIDE(__FILE__), __LINE__, NULL, msg, __VA_ARGS__)
int __cdecl _CrtSetReportMode(int reportType, int reportMode);
_HFILE __cdecl _CrtSetReportFile(int reportType, _HFILE reportFile);
#endif
@ -230,8 +233,6 @@ extern "C" {
#define _CrtGetReportHook() ((_CRT_REPORT_HOOK)0)
#define _CrtSetReportHook2(t,f) ((int)0)
#define _CrtSetReportHookW2(t,f) ((int)0)
#define _CrtSetReportMode(t,f) ((int)0)
#define _CrtSetReportFile(t,f) ((_HFILE)0)
#define _CrtSetBreakAlloc(a) ((long)0)
#define _CrtSetAllocHook(f) ((_CRT_ALLOC_HOOK)0)

View file

@ -16,6 +16,8 @@
#include <windows.h>
#undef OutputDebugString
#undef _CrtSetReportMode
#undef _CrtSetReportFile
#define DBGRPT_MAX_BUFFER_SIZE 4096
#define DBGRPT_ASSERT_PREFIX_MESSAGE "Assertion failed: "
@ -38,6 +40,13 @@ static const wchar_t* _CrtModeMessages[_CRT_ERRCNT] =
L"Error",
L"Assertion Failed"
};
// Report files
static _HFILE _CrtReportFiles[_CRT_ERRCNT] =
{
_CRTDBG_INVALID_HFILE,
_CRTDBG_INVALID_HFILE,
_CRTDBG_INVALID_HFILE
};
// Manually delay-load as to not have a dependency on user32
typedef int (WINAPI *tMessageBoxW)(_In_opt_ HWND hWnd, _In_opt_ LPCWSTR lpText, _In_opt_ LPCWSTR lpCaption, _In_ UINT uType);
@ -57,6 +66,7 @@ struct dbgrpt_char_traits<char>
static const char_t* szUnknownFile;
static void OutputDebugString(const char_t* message);
static size_t StringLength(const char_t* str) { return strlen(str); }
};
template<>
@ -69,13 +79,13 @@ struct dbgrpt_char_traits<wchar_t>
static const char_t* szUnknownFile;
static void OutputDebugString(const char_t* message);
static size_t StringLength(const char_t* str) { return wcslen(str); };
};
// Shortcut
typedef dbgrpt_char_traits<char> achar_traits;
typedef dbgrpt_char_traits<wchar_t> wchar_traits;
const wchar_t* achar_traits::szAssertionMessage =
L"Debug %s!\n"
L"%s%hs" /* module */
@ -97,17 +107,16 @@ const wchar_traits::char_t* wchar_traits::szEmptyString = L"";
const achar_traits::char_t* achar_traits::szUnknownFile = "<unknown file>";
const wchar_traits::char_t* wchar_traits::szUnknownFile = L"<unknown file>";
void achar_traits::OutputDebugString(const char* message)
inline void achar_traits::OutputDebugString(const char* message)
{
OutputDebugStringA(message);
}
void wchar_traits::OutputDebugString(const wchar_t* message)
inline void wchar_traits::OutputDebugString(const wchar_t* message)
{
OutputDebugStringW(message);
}
static
HMODULE _CrtGetUser32()
{
@ -221,6 +230,46 @@ void _CrtLeaveDbgReport(int reportType)
_InterlockedDecrement(&_CrtInAssert);
}
EXTERN_C
int __cdecl _CrtSetReportMode(int reportType, int reportMode)
{
if (reportType >= _CRT_ERRCNT || reportType < 0)
return 0;
int oldReportMode = _CrtModeOutputFormat[reportType];
if (reportMode != _CRTDBG_REPORT_MODE)
_CrtModeOutputFormat[reportType] = reportMode;
return oldReportMode;
}
EXTERN_C
_HFILE __cdecl _CrtSetReportFile(int reportType, _HFILE reportFile)
{
if (reportType >= _CRT_ERRCNT || reportType < 0)
return NULL;
_HFILE oldReportFile = _CrtReportFiles[reportType];
if (reportFile != _CRTDBG_REPORT_FILE)
_CrtReportFiles[reportType] = reportFile;
return oldReportFile;
}
template <typename char_t>
static inline BOOL _CrtDbgReportToFile(HANDLE hFile, const char_t* szMsg)
{
typedef dbgrpt_char_traits<char_t> traits;
if (hFile == _CRTDBG_INVALID_HFILE || hFile == NULL)
return FALSE;
if (hFile == _CRTDBG_FILE_STDOUT)
hFile = ::GetStdHandle(STD_OUTPUT_HANDLE);
else if (hFile == _CRTDBG_FILE_STDERR)
hFile = ::GetStdHandle(STD_ERROR_HANDLE);
DWORD cbMsg = (DWORD)(traits::StringLength(szMsg) * sizeof(char_t));
return ::WriteFile(hFile, szMsg, cbMsg, &cbMsg, NULL);
}
template <typename char_t>
static int _CrtHandleDbgReport(int reportType, const char_t* szCompleteMessage, const char_t* szFormatted,
@ -230,8 +279,7 @@ static int _CrtHandleDbgReport(int reportType, const char_t* szCompleteMessage,
if (_CrtModeOutputFormat[reportType] & _CRTDBG_MODE_FILE)
{
OutputDebugStringA("ERROR: Please implement _CrtSetReportFile first\n");
_CrtDbgBreak();
_CrtDbgReportToFile<char_t>(_CrtReportFiles[reportType], szCompleteMessage);
}
if (_CrtModeOutputFormat[reportType] & _CRTDBG_MODE_DEBUG)

View file

@ -15,6 +15,7 @@ list(APPEND CRT_MISC_SOURCE
misc/amsg.c
misc/assert.c
misc/crt_init.c
misc/dbgrpt.cpp
misc/environ.c
misc/getargs.c
misc/i10output.c