Something went wrong. Try again.
Reactos
Something went wrong. Try again.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693/****dbgrptt.c - Debug CRT Reporting Functions** Copyright (c) Microsoft Corporation. All rights reserved.**Purpose:********************************************************************************/
#ifndef _DEBUG #error This file is supported only in debug builds #define _DEBUG // For design-time support, when editing/viewing CRT sources#endif
#include <corecrt_internal.h>#include <errno.h>#include <malloc.h>#include <minmax.h>#include <stdio.h>#include <stdlib.h>
extern "C" int __cdecl __acrt_MessageWindowA( int report_type, void* return_address, char const* file_name, char const* line_number, char const* module_name, char const* user_message );
extern "C" int __cdecl __acrt_MessageWindowW( int report_type, void* return_address, wchar_t const* file_name, wchar_t const* line_number, wchar_t const* module_name, wchar_t const* user_message );
extern "C" {
_CRT_REPORT_HOOK _pfnReportHook;
__crt_report_hook_node<char> *_pReportHookList;__crt_report_hook_node<wchar_t> *_pReportHookListW;
long _crtAssertBusy = -1;
// Enclaves only support MODE_DEBUG for error output#ifdef _UCRT_ENCLAVE_BUILD
int const _CrtDbgMode[_CRT_ERRCNT]{ _CRTDBG_MODE_DEBUG, _CRTDBG_MODE_DEBUG, _CRTDBG_MODE_DEBUG};
_HFILE const _CrtDbgFile[_CRT_ERRCNT]{ _CRTDBG_INVALID_HFILE, _CRTDBG_INVALID_HFILE, _CRTDBG_INVALID_HFILE};
#else
int _CrtDbgMode[_CRT_ERRCNT]{ _CRTDBG_MODE_DEBUG, _CRTDBG_MODE_WNDW, _CRTDBG_MODE_WNDW};
_HFILE _CrtDbgFile[_CRT_ERRCNT]{ _CRTDBG_INVALID_HFILE, _CRTDBG_INVALID_HFILE, _CRTDBG_INVALID_HFILE};
/****int _CrtSetReportMode - set the reporting mode for a given report type**Purpose:* set the reporting mode for a given report type**Entry:* int nRptType - the report type* int fMode - new mode for given report type**Exit:* previous mode for given report type**Exceptions:* Input parameters are validated. Refer to the validation section of the function.********************************************************************************/int __cdecl _CrtSetReportMode( int nRptType, int fMode ){ int oldMode;
/* validation section */ _VALIDATE_RETURN(nRptType >= 0 && nRptType < _CRT_ERRCNT, EINVAL, -1); _VALIDATE_RETURN( fMode == _CRTDBG_REPORT_MODE || (fMode & ~(_CRTDBG_MODE_FILE | _CRTDBG_MODE_DEBUG | _CRTDBG_MODE_WNDW)) == 0, EINVAL, -1);
if (fMode == _CRTDBG_REPORT_MODE) return _CrtDbgMode[nRptType];
oldMode = _CrtDbgMode[nRptType];
_CrtDbgMode[nRptType] = fMode;
return oldMode;}
/****int _CrtSetReportFile - set the reporting file for a given report type**Purpose:* set the reporting file for a given report type**Entry:* int nRptType - the report type* _HFILE hFile - new file for given report type**Exit:* previous file for given report type**Exceptions:* Input parameters are validated. Refer to the validation section of the function.********************************************************************************/_HFILE __cdecl _CrtSetReportFile( int nRptType, _HFILE hFile ){ _HFILE oldFile;
/* validation section */ _VALIDATE_RETURN(nRptType >= 0 && nRptType < _CRT_ERRCNT, EINVAL, _CRTDBG_HFILE_ERROR);
if (hFile == _CRTDBG_REPORT_FILE) return _CrtDbgFile[nRptType];
oldFile = _CrtDbgFile[nRptType];
if (_CRTDBG_FILE_STDOUT == hFile) _CrtDbgFile[nRptType] = GetStdHandle(STD_OUTPUT_HANDLE); else if (_CRTDBG_FILE_STDERR == hFile) _CrtDbgFile[nRptType] = GetStdHandle(STD_ERROR_HANDLE); else _CrtDbgFile[nRptType] = hFile;
return oldFile;}
#endif /* _UCRT_ENCLAVE_BUILD */
/****_CRT_REPORT_HOOK _CrtSetReportHook() - set client report hook**Purpose:* set client report hook. This function is provided only in ANSI* for backward compatibility. No Unicode Version of this function exists**Entry:* _CRT_REPORT_HOOK pfnNewHook - new report hook**Exit:* return previous hook**Exceptions:********************************************************************************/
_CRT_REPORT_HOOK __cdecl _CrtSetReportHook(_CRT_REPORT_HOOK pfnNewHook){ _CRT_REPORT_HOOK pfnOldHook = _pfnReportHook; _pfnReportHook = pfnNewHook; return pfnOldHook;}
/****_CRT_REPORT_HOOK _CrtGetReportHook() - get client report hook**Purpose:* get client report hook.**Entry:**Exit:* return current hook**Exceptions:********************************************************************************/
_CRT_REPORT_HOOK __cdecl _CrtGetReportHook(void){ return _pfnReportHook;}
#define ASSERTINTRO1 "Assertion failed: "#define ASSERTINTRO2 "Assertion failed!"
/****int _VCrtDbgReportA() - _CrtDbgReport calls into this function**Purpose:* See remarks for _CrtDbgReport.**Entry:* int nRptType - report type* char const* szFile - file name* int nLine - line number* char const* szModule - module name* char const* szFormat - format string* va_list arglist - var args arglist**Exit:* See remarks for _CrtDbgReport**Exceptions:********************************************************************************/
#pragma warning(push)#pragma warning(disable:6262)// prefast (6262): This func uses lots of stack because we want to tolerate very large reports, and we can't use malloc here.int __cdecl _VCrtDbgReportA( int nRptType, void * returnAddress, char const* szFile, int nLine, char const* szModule, char const* szFormat, va_list arglist ){ int retval=0; int handled=FALSE;
char szLineMessage[DBGRPT_MAX_MSG]{0}; char szOutMessage [DBGRPT_MAX_MSG]{0}; wchar_t szOutMessage2[DBGRPT_MAX_MSG]{0}; char szUserMessage[DBGRPT_MAX_MSG]{0};
if (nRptType < 0 || nRptType >= _CRT_ERRCNT) return -1;
/* * handle the (hopefully rare) case of * * 1) ASSERT while already dealing with an ASSERT * or * 2) two threads asserting at the same time */
__try { if (_CRT_ASSERT == nRptType && _InterlockedIncrement(&_crtAssertBusy) > 0) { /* use only 'safe' functions -- must not assert in here! */
_ERRCHECK(_itoa_s(nLine, szLineMessage, DBGRPT_MAX_MSG, 10));
__acrt_OutputDebugStringA("Second Chance Assertion Failed: File "); __acrt_OutputDebugStringA(szFile ? szFile : "<file unknown>"); __acrt_OutputDebugStringA(", Line "); __acrt_OutputDebugStringA(szLineMessage); __acrt_OutputDebugStringA("\n");
_CrtDbgBreak(); retval=-1; __leave; }
// Leave space for ASSERTINTRO1 and "\r\n" if (szFormat) { int szlen = 0; _ERRCHECK_SPRINTF(szlen = _vsnprintf_s(szUserMessage, DBGRPT_MAX_MSG, DBGRPT_MAX_MSG - 2- max(sizeof(ASSERTINTRO1),sizeof(ASSERTINTRO2)), szFormat, arglist)); if (szlen < 0) { _ERRCHECK(strcpy_s(szUserMessage, DBGRPT_MAX_MSG, DBGRPT_TOOLONGMSG)); } }
if (_CRT_ASSERT == nRptType) { _ERRCHECK(strcpy_s(szLineMessage, DBGRPT_MAX_MSG, szFormat ? ASSERTINTRO1 : ASSERTINTRO2)); }
_ERRCHECK(strcat_s(szLineMessage, DBGRPT_MAX_MSG, szUserMessage));
if (_CRT_ASSERT == nRptType) { if (_CrtDbgMode[nRptType] & _CRTDBG_MODE_FILE) { _ERRCHECK(strcat_s(szLineMessage, DBGRPT_MAX_MSG, "\r")); }
_ERRCHECK(strcat_s(szLineMessage, DBGRPT_MAX_MSG, "\n")); }
if (szFile) { int szlen = 0; _ERRCHECK_SPRINTF(szlen = _snprintf_s(szOutMessage, DBGRPT_MAX_MSG, DBGRPT_MAX_MSG - 1, "%s(%d) : %s", szFile, nLine, szLineMessage)); if (szlen < 0) { _ERRCHECK(strcpy_s(szOutMessage, DBGRPT_MAX_MSG, DBGRPT_TOOLONGMSG)); } } else { _ERRCHECK(strcpy_s(szOutMessage, DBGRPT_MAX_MSG, szLineMessage)); }
{ size_t ret = 0; errno_t e = 0; _ERRCHECK_EINVAL_ERANGE(e = mbstowcs_s(&ret, szOutMessage2, DBGRPT_MAX_MSG, szOutMessage, _TRUNCATE)); if(e != 0) { _ERRCHECK(wcscpy_s(szOutMessage2, DBGRPT_MAX_MSG, _CRT_WIDE(DBGRPT_INVALIDMSG))); } }
/* User hook may handle report. We have to check the ANSI Hook2 List & then the UNICODE Hook2 List. Then we have check any ANSI individual Hook set through SetReportHook */
if (_pReportHookList || _pReportHookListW) { __crt_report_hook_node<char> *pnode=nullptr; __crt_report_hook_node<wchar_t> *pnodeW=nullptr;
__acrt_lock(__acrt_debug_lock); __try { for (pnode = _pReportHookList; pnode; pnode = pnode->next) { int hook_retval=0; if (pnode->hook(nRptType, szOutMessage, &hook_retval)) { handled=TRUE; retval=hook_retval; __leave; } }
for (pnodeW = _pReportHookListW; pnodeW; pnodeW = pnodeW->next) { int hook_retval=0; if (pnodeW->hook(nRptType, szOutMessage2, &hook_retval)) { handled=TRUE; retval=hook_retval; __leave; } } } __finally { __acrt_unlock(__acrt_debug_lock); } __endtry }
if (handled) __leave;
if (_pfnReportHook) { int hook_retval=0; if (_pfnReportHook(nRptType, szOutMessage, &hook_retval)) { retval = hook_retval; __leave; } }
if (_CrtDbgMode[nRptType] & _CRTDBG_MODE_FILE) { if (_CrtDbgFile[nRptType] != _CRTDBG_INVALID_HFILE) { DWORD bytes_written = 0; WriteFile(_CrtDbgFile[nRptType], szOutMessage, static_cast<DWORD>(strlen(szOutMessage)), &bytes_written, nullptr); } }
if (_CrtDbgMode[nRptType] & _CRTDBG_MODE_DEBUG) { __acrt_OutputDebugStringA(szOutMessage); }
if (_CrtDbgMode[nRptType] & _CRTDBG_MODE_WNDW) { szLineMessage[0] = 0; if (nLine) { _ERRCHECK(_itoa_s(nLine, szLineMessage, DBGRPT_MAX_MSG, 10)); }
retval = __acrt_MessageWindowA(nRptType, returnAddress, szFile, (nLine ? szLineMessage : nullptr), szModule, szUserMessage); } } __finally { if (_CRT_ASSERT == nRptType) { _InterlockedDecrement(&_crtAssertBusy); } } __endtry
return retval;}#pragma warning(pop)
/****int _VCrtDbgReportW() - _CrtDbgReportW calls into this function**Purpose:* See remarks for _CrtDbgReport.**Entry:* int nRptType - report type* wchar_t const* szFile - file name* int nLine - line number* wchar_t const* szModule - module name* wchar_t const* szFormat - format string* va_list arglist - var args arglist**Exit:* See remarks for _CrtDbgReport**Exceptions:********************************************************************************/
#pragma warning(push)#pragma warning(disable:6262)// prefast(6262): This func uses lots of stack because we want to tolerate very large reports, and we can't use malloc here.int __cdecl _VCrtDbgReportW( int nRptType, void * returnAddress, wchar_t const* szFile, int nLine, wchar_t const* szModule, wchar_t const* szFormat, va_list arglist ){ int retval=0; int handled=FALSE; wchar_t szLineMessage[DBGRPT_MAX_MSG] = {0}; wchar_t szOutMessage[DBGRPT_MAX_MSG] = {0}; char szOutMessage2[DBGRPT_MAX_MSG] = {0}; wchar_t szUserMessage[DBGRPT_MAX_MSG] = {0};
if (nRptType < 0 || nRptType >= _CRT_ERRCNT) return -1;
/* * handle the (hopefully rare) case of * * 1) ASSERT while already dealing with an ASSERT * or * 2) two threads asserting at the same time */
__try { if (_CRT_ASSERT == nRptType && _InterlockedIncrement(&_crtAssertBusy) > 0) { /* use only 'safe' functions -- must not assert in here! */
_ERRCHECK(_itow_s(nLine, szLineMessage, DBGRPT_MAX_MSG, 10));
OutputDebugStringW(L"Second Chance Assertion Failed: File "); OutputDebugStringW(szFile ? szFile : L"<file unknown>"); OutputDebugStringW(L", Line "); OutputDebugStringW(szLineMessage); OutputDebugStringW(L"\n");
_CrtDbgBreak(); retval = -1; __leave; }
if (szFormat) { // Leave space for ASSERTINTRO{1,2} and "\r\n" size_t const max_assert_intro_count = __max(_countof(ASSERTINTRO1), _countof(ASSERTINTRO2)); size_t const max_user_message_count = _countof(szUserMessage) - 2 - max_assert_intro_count;
// Force use of the legacy stdio wide character format specifiers // mode for source compatibility. If we ever revisit support for // the standard format specifiers, we'll need to revisit this as // well. int szlen = 0; _ERRCHECK_SPRINTF(szlen = __stdio_common_vsnwprintf_s( _CRT_INTERNAL_PRINTF_LEGACY_WIDE_SPECIFIERS, szUserMessage, _countof(szUserMessage), max_user_message_count, szFormat, nullptr, arglist)); if (szlen < 0) { _ERRCHECK(wcscpy_s(szUserMessage, DBGRPT_MAX_MSG, _CRT_WIDE(DBGRPT_TOOLONGMSG))); } }
if (_CRT_ASSERT == nRptType) _ERRCHECK(wcscpy_s(szLineMessage, DBGRPT_MAX_MSG, szFormat ? _CRT_WIDE(ASSERTINTRO1) : _CRT_WIDE(ASSERTINTRO2)));
_ERRCHECK(wcscat_s(szLineMessage, DBGRPT_MAX_MSG, szUserMessage));
if (_CRT_ASSERT == nRptType) { if (_CrtDbgMode[nRptType] & _CRTDBG_MODE_FILE) _ERRCHECK(wcscat_s(szLineMessage, DBGRPT_MAX_MSG, L"\r")); { _ERRCHECK(wcscat_s(szLineMessage, DBGRPT_MAX_MSG, L"\n")); } }
if (szFile) { int szlen = 0; _ERRCHECK_SPRINTF(szlen = _snwprintf_s(szOutMessage, DBGRPT_MAX_MSG, DBGRPT_MAX_MSG, L"%ls(%d) : %ls", szFile, nLine, szLineMessage)); if (szlen < 0) _ERRCHECK(wcscpy_s(szOutMessage, DBGRPT_MAX_MSG, _CRT_WIDE(DBGRPT_TOOLONGMSG))); } else { _ERRCHECK(wcscpy_s(szOutMessage, DBGRPT_MAX_MSG, szLineMessage)); }
/* scope */ { errno_t e = _ERRCHECK_EINVAL_ERANGE(wcstombs_s(nullptr, szOutMessage2, DBGRPT_MAX_MSG, szOutMessage, _TRUNCATE)); if(e != 0) _ERRCHECK(strcpy_s(szOutMessage2, DBGRPT_MAX_MSG, DBGRPT_INVALIDMSG)); }
/* User hook may handle report. We have to check the ANSI Hook2 List & then the UNICODE Hook2 List. Then we have check any ANSI individual Hook set through SetReportHook */
if (_pReportHookList || _pReportHookListW) { __crt_report_hook_node<char> *pnode=nullptr; __crt_report_hook_node<wchar_t> *pnodeW=nullptr;
__acrt_lock(__acrt_debug_lock); __try { for (pnode = _pReportHookList; pnode; pnode = pnode->next) { int hook_retval=0; if (pnode->hook(nRptType, szOutMessage2, &hook_retval)) { retval=hook_retval; handled=TRUE; __leave; } }
for (pnodeW = _pReportHookListW; pnodeW; pnodeW = pnodeW->next) { int hook_retval=0; if (pnodeW->hook(nRptType, szOutMessage, &hook_retval)) { retval=hook_retval; handled=TRUE; __leave; } } } __finally { __acrt_unlock(__acrt_debug_lock); } __endtry }
if (handled) __leave;
if(_pfnReportHook) { int hook_retval=0; if (_pfnReportHook(nRptType, szOutMessage2, &hook_retval)) { retval = hook_retval; __leave; } }
if ((_CrtDbgMode[nRptType] & _CRTDBG_MODE_FILE) && _CrtDbgFile[nRptType] != _CRTDBG_INVALID_HFILE) { /* Use WriteConsole for Consoles, WriteFile otherwise */ switch (GetFileType(_CrtDbgFile[nRptType])) { case FILE_TYPE_CHAR: { DWORD characters_written = 0; if (WriteConsoleW(_CrtDbgFile[nRptType], szOutMessage, static_cast<DWORD>(wcslen(szOutMessage)), &characters_written, nullptr)) break;
/* If WriteConsole fails & LastError is ERROR_INVALID_VALUE, then the console is redirected */ if (GetLastError() != ERROR_INVALID_HANDLE) break; } default: { char szaOutMessage[DBGRPT_MAX_MSG]; size_t ret = 0; errno_t e = _ERRCHECK_EINVAL_ERANGE(wcstombs_s(&ret, szaOutMessage, DBGRPT_MAX_MSG, szOutMessage, _TRUNCATE));
if (e != 0 && e != STRUNCATE) { DWORD bytes_written = 0; WriteFile(_CrtDbgFile[nRptType], szOutMessage, static_cast<DWORD>(wcslen(szOutMessage)) * 2, &bytes_written, nullptr); } else { /* ret counts for the null terminator as well */ if (ret > 0) { --ret; }
DWORD bytes_written = 0; WriteFile(_CrtDbgFile[nRptType], szaOutMessage, static_cast<DWORD>(ret), &bytes_written, nullptr); } } } }
if (_CrtDbgMode[nRptType] & _CRTDBG_MODE_DEBUG) { ::OutputDebugStringW(szOutMessage); }
if (_CrtDbgMode[nRptType] & _CRTDBG_MODE_WNDW) { szLineMessage[0] = 0; if (nLine) { _ERRCHECK(_itow_s(nLine, szLineMessage, DBGRPT_MAX_MSG, 10)); } retval = __acrt_MessageWindowW(nRptType, returnAddress, szFile, (nLine ? szLineMessage : nullptr), szModule, szUserMessage); } } __finally { if (_CRT_ASSERT == nRptType) { _InterlockedDecrement(&_crtAssertBusy); } } __endtry
return retval;}#pragma warning(pop)
} // extern "C"