xref: /reactos/sdk/lib/ucrt/misc/dbgrptt.cpp (revision e98e9000)
104e0dc4aSTimo Kreuzer /***
204e0dc4aSTimo Kreuzer *dbgrptt.c - Debug CRT Reporting Functions
304e0dc4aSTimo Kreuzer *
404e0dc4aSTimo Kreuzer *       Copyright (c) Microsoft Corporation. All rights reserved.
504e0dc4aSTimo Kreuzer *
604e0dc4aSTimo Kreuzer *Purpose:
704e0dc4aSTimo Kreuzer *
804e0dc4aSTimo Kreuzer *******************************************************************************/
904e0dc4aSTimo Kreuzer 
1004e0dc4aSTimo Kreuzer #ifndef _DEBUG
1104e0dc4aSTimo Kreuzer     #error This file is supported only in debug builds
1204e0dc4aSTimo Kreuzer     #define _DEBUG // For design-time support, when editing/viewing CRT sources
1304e0dc4aSTimo Kreuzer #endif
1404e0dc4aSTimo Kreuzer 
1504e0dc4aSTimo Kreuzer #include <corecrt_internal.h>
1604e0dc4aSTimo Kreuzer #include <errno.h>
1704e0dc4aSTimo Kreuzer #include <malloc.h>
1804e0dc4aSTimo Kreuzer #include <minmax.h>
1904e0dc4aSTimo Kreuzer #include <stdio.h>
2004e0dc4aSTimo Kreuzer #include <stdlib.h>
2104e0dc4aSTimo Kreuzer 
2204e0dc4aSTimo Kreuzer 
2304e0dc4aSTimo Kreuzer 
2404e0dc4aSTimo Kreuzer extern "C" int __cdecl __acrt_MessageWindowA(
2504e0dc4aSTimo Kreuzer     int         report_type,
2604e0dc4aSTimo Kreuzer     void*       return_address,
2704e0dc4aSTimo Kreuzer     char const* file_name,
2804e0dc4aSTimo Kreuzer     char const* line_number,
2904e0dc4aSTimo Kreuzer     char const* module_name,
3004e0dc4aSTimo Kreuzer     char const* user_message
3104e0dc4aSTimo Kreuzer     );
3204e0dc4aSTimo Kreuzer 
3304e0dc4aSTimo Kreuzer extern "C" int __cdecl __acrt_MessageWindowW(
3404e0dc4aSTimo Kreuzer     int            report_type,
3504e0dc4aSTimo Kreuzer     void*          return_address,
3604e0dc4aSTimo Kreuzer     wchar_t const* file_name,
3704e0dc4aSTimo Kreuzer     wchar_t const* line_number,
3804e0dc4aSTimo Kreuzer     wchar_t const* module_name,
3904e0dc4aSTimo Kreuzer     wchar_t const* user_message
4004e0dc4aSTimo Kreuzer     );
4104e0dc4aSTimo Kreuzer 
4204e0dc4aSTimo Kreuzer extern "C" {
4304e0dc4aSTimo Kreuzer 
4404e0dc4aSTimo Kreuzer _CRT_REPORT_HOOK _pfnReportHook;
4504e0dc4aSTimo Kreuzer 
4604e0dc4aSTimo Kreuzer __crt_report_hook_node<char> *_pReportHookList;
4704e0dc4aSTimo Kreuzer __crt_report_hook_node<wchar_t> *_pReportHookListW;
4804e0dc4aSTimo Kreuzer 
4904e0dc4aSTimo Kreuzer long _crtAssertBusy = -1;
5004e0dc4aSTimo Kreuzer 
5104e0dc4aSTimo Kreuzer // Enclaves only support MODE_DEBUG for error output
5204e0dc4aSTimo Kreuzer #ifdef _UCRT_ENCLAVE_BUILD
5304e0dc4aSTimo Kreuzer 
5404e0dc4aSTimo Kreuzer int const _CrtDbgMode[_CRT_ERRCNT]
5504e0dc4aSTimo Kreuzer {
5604e0dc4aSTimo Kreuzer     _CRTDBG_MODE_DEBUG,
5704e0dc4aSTimo Kreuzer     _CRTDBG_MODE_DEBUG,
5804e0dc4aSTimo Kreuzer     _CRTDBG_MODE_DEBUG
5904e0dc4aSTimo Kreuzer };
6004e0dc4aSTimo Kreuzer 
6104e0dc4aSTimo Kreuzer _HFILE const _CrtDbgFile[_CRT_ERRCNT]
6204e0dc4aSTimo Kreuzer {
6304e0dc4aSTimo Kreuzer     _CRTDBG_INVALID_HFILE,
6404e0dc4aSTimo Kreuzer     _CRTDBG_INVALID_HFILE,
6504e0dc4aSTimo Kreuzer     _CRTDBG_INVALID_HFILE
6604e0dc4aSTimo Kreuzer };
6704e0dc4aSTimo Kreuzer 
6804e0dc4aSTimo Kreuzer #else
6904e0dc4aSTimo Kreuzer 
7004e0dc4aSTimo Kreuzer int _CrtDbgMode[_CRT_ERRCNT]
7104e0dc4aSTimo Kreuzer {
7204e0dc4aSTimo Kreuzer     _CRTDBG_MODE_DEBUG,
7304e0dc4aSTimo Kreuzer     _CRTDBG_MODE_WNDW,
7404e0dc4aSTimo Kreuzer     _CRTDBG_MODE_WNDW
7504e0dc4aSTimo Kreuzer };
7604e0dc4aSTimo Kreuzer 
7704e0dc4aSTimo Kreuzer _HFILE _CrtDbgFile[_CRT_ERRCNT]
7804e0dc4aSTimo Kreuzer {
7904e0dc4aSTimo Kreuzer     _CRTDBG_INVALID_HFILE,
8004e0dc4aSTimo Kreuzer     _CRTDBG_INVALID_HFILE,
8104e0dc4aSTimo Kreuzer     _CRTDBG_INVALID_HFILE
8204e0dc4aSTimo Kreuzer };
8304e0dc4aSTimo Kreuzer 
8404e0dc4aSTimo Kreuzer /***
8504e0dc4aSTimo Kreuzer *int _CrtSetReportMode - set the reporting mode for a given report type
8604e0dc4aSTimo Kreuzer *
8704e0dc4aSTimo Kreuzer *Purpose:
8804e0dc4aSTimo Kreuzer *       set the reporting mode for a given report type
8904e0dc4aSTimo Kreuzer *
9004e0dc4aSTimo Kreuzer *Entry:
9104e0dc4aSTimo Kreuzer *       int nRptType    - the report type
9204e0dc4aSTimo Kreuzer *       int fMode       - new mode for given report type
9304e0dc4aSTimo Kreuzer *
9404e0dc4aSTimo Kreuzer *Exit:
9504e0dc4aSTimo Kreuzer *       previous mode for given report type
9604e0dc4aSTimo Kreuzer *
9704e0dc4aSTimo Kreuzer *Exceptions:
9804e0dc4aSTimo Kreuzer *       Input parameters are validated. Refer to the validation section of the function.
9904e0dc4aSTimo Kreuzer *
10004e0dc4aSTimo Kreuzer *******************************************************************************/
_CrtSetReportMode(int nRptType,int fMode)10104e0dc4aSTimo Kreuzer int __cdecl _CrtSetReportMode(
10204e0dc4aSTimo Kreuzer     int nRptType,
10304e0dc4aSTimo Kreuzer     int fMode
10404e0dc4aSTimo Kreuzer     )
10504e0dc4aSTimo Kreuzer {
10604e0dc4aSTimo Kreuzer     int oldMode;
10704e0dc4aSTimo Kreuzer 
10804e0dc4aSTimo Kreuzer     /* validation section */
10904e0dc4aSTimo Kreuzer     _VALIDATE_RETURN(nRptType >= 0 && nRptType < _CRT_ERRCNT, EINVAL, -1);
11004e0dc4aSTimo Kreuzer     _VALIDATE_RETURN(
11104e0dc4aSTimo Kreuzer         fMode == _CRTDBG_REPORT_MODE ||
11204e0dc4aSTimo Kreuzer         (fMode & ~(_CRTDBG_MODE_FILE | _CRTDBG_MODE_DEBUG | _CRTDBG_MODE_WNDW)) == 0,
11304e0dc4aSTimo Kreuzer         EINVAL,
11404e0dc4aSTimo Kreuzer         -1);
11504e0dc4aSTimo Kreuzer 
11604e0dc4aSTimo Kreuzer     if (fMode == _CRTDBG_REPORT_MODE)
11704e0dc4aSTimo Kreuzer         return _CrtDbgMode[nRptType];
11804e0dc4aSTimo Kreuzer 
11904e0dc4aSTimo Kreuzer     oldMode = _CrtDbgMode[nRptType];
12004e0dc4aSTimo Kreuzer 
12104e0dc4aSTimo Kreuzer     _CrtDbgMode[nRptType] = fMode;
12204e0dc4aSTimo Kreuzer 
12304e0dc4aSTimo Kreuzer     return oldMode;
12404e0dc4aSTimo Kreuzer }
12504e0dc4aSTimo Kreuzer 
12604e0dc4aSTimo Kreuzer /***
12704e0dc4aSTimo Kreuzer *int _CrtSetReportFile - set the reporting file for a given report type
12804e0dc4aSTimo Kreuzer *
12904e0dc4aSTimo Kreuzer *Purpose:
13004e0dc4aSTimo Kreuzer *       set the reporting file for a given report type
13104e0dc4aSTimo Kreuzer *
13204e0dc4aSTimo Kreuzer *Entry:
13304e0dc4aSTimo Kreuzer *       int nRptType    - the report type
13404e0dc4aSTimo Kreuzer *       _HFILE hFile    - new file for given report type
13504e0dc4aSTimo Kreuzer *
13604e0dc4aSTimo Kreuzer *Exit:
13704e0dc4aSTimo Kreuzer *       previous file for given report type
13804e0dc4aSTimo Kreuzer *
13904e0dc4aSTimo Kreuzer *Exceptions:
14004e0dc4aSTimo Kreuzer *       Input parameters are validated. Refer to the validation section of the function.
14104e0dc4aSTimo Kreuzer *
14204e0dc4aSTimo Kreuzer *******************************************************************************/
_CrtSetReportFile(int nRptType,_HFILE hFile)14304e0dc4aSTimo Kreuzer _HFILE __cdecl _CrtSetReportFile(
14404e0dc4aSTimo Kreuzer     int nRptType,
14504e0dc4aSTimo Kreuzer     _HFILE hFile
14604e0dc4aSTimo Kreuzer     )
14704e0dc4aSTimo Kreuzer {
14804e0dc4aSTimo Kreuzer     _HFILE oldFile;
14904e0dc4aSTimo Kreuzer 
15004e0dc4aSTimo Kreuzer     /* validation section */
15104e0dc4aSTimo Kreuzer     _VALIDATE_RETURN(nRptType >= 0 && nRptType < _CRT_ERRCNT, EINVAL, _CRTDBG_HFILE_ERROR);
15204e0dc4aSTimo Kreuzer 
15304e0dc4aSTimo Kreuzer     if (hFile == _CRTDBG_REPORT_FILE)
15404e0dc4aSTimo Kreuzer         return _CrtDbgFile[nRptType];
15504e0dc4aSTimo Kreuzer 
15604e0dc4aSTimo Kreuzer     oldFile = _CrtDbgFile[nRptType];
15704e0dc4aSTimo Kreuzer 
15804e0dc4aSTimo Kreuzer     if (_CRTDBG_FILE_STDOUT == hFile)
15904e0dc4aSTimo Kreuzer         _CrtDbgFile[nRptType] = GetStdHandle(STD_OUTPUT_HANDLE);
16004e0dc4aSTimo Kreuzer     else if (_CRTDBG_FILE_STDERR == hFile)
16104e0dc4aSTimo Kreuzer         _CrtDbgFile[nRptType] = GetStdHandle(STD_ERROR_HANDLE);
16204e0dc4aSTimo Kreuzer     else
16304e0dc4aSTimo Kreuzer         _CrtDbgFile[nRptType] = hFile;
16404e0dc4aSTimo Kreuzer 
16504e0dc4aSTimo Kreuzer     return oldFile;
16604e0dc4aSTimo Kreuzer }
16704e0dc4aSTimo Kreuzer 
16804e0dc4aSTimo Kreuzer #endif /* _UCRT_ENCLAVE_BUILD */
16904e0dc4aSTimo Kreuzer 
17004e0dc4aSTimo Kreuzer /***
17104e0dc4aSTimo Kreuzer *_CRT_REPORT_HOOK _CrtSetReportHook() - set client report hook
17204e0dc4aSTimo Kreuzer *
17304e0dc4aSTimo Kreuzer *Purpose:
17404e0dc4aSTimo Kreuzer *       set client report hook. This function is provided only in ANSI
17504e0dc4aSTimo Kreuzer *       for backward compatibility. No Unicode Version of this function exists
17604e0dc4aSTimo Kreuzer *
17704e0dc4aSTimo Kreuzer *Entry:
17804e0dc4aSTimo Kreuzer *       _CRT_REPORT_HOOK pfnNewHook - new report hook
17904e0dc4aSTimo Kreuzer *
18004e0dc4aSTimo Kreuzer *Exit:
18104e0dc4aSTimo Kreuzer *       return previous hook
18204e0dc4aSTimo Kreuzer *
18304e0dc4aSTimo Kreuzer *Exceptions:
18404e0dc4aSTimo Kreuzer *
18504e0dc4aSTimo Kreuzer *******************************************************************************/
18604e0dc4aSTimo Kreuzer 
_CrtSetReportHook(_CRT_REPORT_HOOK pfnNewHook)18704e0dc4aSTimo Kreuzer _CRT_REPORT_HOOK __cdecl _CrtSetReportHook(_CRT_REPORT_HOOK pfnNewHook)
18804e0dc4aSTimo Kreuzer {
18904e0dc4aSTimo Kreuzer     _CRT_REPORT_HOOK pfnOldHook = _pfnReportHook;
19004e0dc4aSTimo Kreuzer     _pfnReportHook = pfnNewHook;
19104e0dc4aSTimo Kreuzer     return pfnOldHook;
19204e0dc4aSTimo Kreuzer }
19304e0dc4aSTimo Kreuzer 
19404e0dc4aSTimo Kreuzer /***
19504e0dc4aSTimo Kreuzer *_CRT_REPORT_HOOK _CrtGetReportHook() - get client report hook
19604e0dc4aSTimo Kreuzer *
19704e0dc4aSTimo Kreuzer *Purpose:
19804e0dc4aSTimo Kreuzer *       get client report hook.
19904e0dc4aSTimo Kreuzer *
20004e0dc4aSTimo Kreuzer *Entry:
20104e0dc4aSTimo Kreuzer *
20204e0dc4aSTimo Kreuzer *Exit:
20304e0dc4aSTimo Kreuzer *       return current hook
20404e0dc4aSTimo Kreuzer *
20504e0dc4aSTimo Kreuzer *Exceptions:
20604e0dc4aSTimo Kreuzer *
20704e0dc4aSTimo Kreuzer *******************************************************************************/
20804e0dc4aSTimo Kreuzer 
_CrtGetReportHook(void)20904e0dc4aSTimo Kreuzer _CRT_REPORT_HOOK __cdecl _CrtGetReportHook(void)
21004e0dc4aSTimo Kreuzer {
21104e0dc4aSTimo Kreuzer     return _pfnReportHook;
21204e0dc4aSTimo Kreuzer }
21304e0dc4aSTimo Kreuzer 
21404e0dc4aSTimo Kreuzer #define ASSERTINTRO1 "Assertion failed: "
21504e0dc4aSTimo Kreuzer #define ASSERTINTRO2 "Assertion failed!"
21604e0dc4aSTimo Kreuzer 
21704e0dc4aSTimo Kreuzer /***
21804e0dc4aSTimo Kreuzer *int _VCrtDbgReportA() - _CrtDbgReport calls into this function
21904e0dc4aSTimo Kreuzer *
22004e0dc4aSTimo Kreuzer *Purpose:
22104e0dc4aSTimo Kreuzer *       See remarks for _CrtDbgReport.
22204e0dc4aSTimo Kreuzer *
22304e0dc4aSTimo Kreuzer *Entry:
22404e0dc4aSTimo Kreuzer *       int             nRptType    - report type
22504e0dc4aSTimo Kreuzer *       char const*    szFile      - file name
22604e0dc4aSTimo Kreuzer *       int             nLine       - line number
22704e0dc4aSTimo Kreuzer *       char const*    szModule    - module name
22804e0dc4aSTimo Kreuzer *       char const*    szFormat    - format string
22904e0dc4aSTimo Kreuzer *       va_list         arglist      - var args arglist
23004e0dc4aSTimo Kreuzer *
23104e0dc4aSTimo Kreuzer *Exit:
23204e0dc4aSTimo Kreuzer *       See remarks for _CrtDbgReport
23304e0dc4aSTimo Kreuzer *
23404e0dc4aSTimo Kreuzer *Exceptions:
23504e0dc4aSTimo Kreuzer *
23604e0dc4aSTimo Kreuzer *******************************************************************************/
23704e0dc4aSTimo Kreuzer 
23804e0dc4aSTimo Kreuzer #pragma warning(push)
23904e0dc4aSTimo Kreuzer #pragma warning(disable:6262)
24004e0dc4aSTimo Kreuzer // prefast (6262): This func uses lots of stack because we want to tolerate very large reports, and we can't use malloc here.
_VCrtDbgReportA(int nRptType,void * returnAddress,char const * szFile,int nLine,char const * szModule,char const * szFormat,va_list arglist)24104e0dc4aSTimo Kreuzer int __cdecl _VCrtDbgReportA(
24204e0dc4aSTimo Kreuzer     int nRptType,
24304e0dc4aSTimo Kreuzer     void * returnAddress,
24404e0dc4aSTimo Kreuzer     char const* szFile,
24504e0dc4aSTimo Kreuzer     int nLine,
24604e0dc4aSTimo Kreuzer     char const* szModule,
24704e0dc4aSTimo Kreuzer     char const* szFormat,
24804e0dc4aSTimo Kreuzer     va_list arglist
24904e0dc4aSTimo Kreuzer     )
25004e0dc4aSTimo Kreuzer {
25104e0dc4aSTimo Kreuzer     int retval=0;
25204e0dc4aSTimo Kreuzer     int handled=FALSE;
25304e0dc4aSTimo Kreuzer 
25404e0dc4aSTimo Kreuzer     char    szLineMessage[DBGRPT_MAX_MSG]{0};
25504e0dc4aSTimo Kreuzer     char    szOutMessage [DBGRPT_MAX_MSG]{0};
25604e0dc4aSTimo Kreuzer     wchar_t szOutMessage2[DBGRPT_MAX_MSG]{0};
25704e0dc4aSTimo Kreuzer     char    szUserMessage[DBGRPT_MAX_MSG]{0};
25804e0dc4aSTimo Kreuzer 
25904e0dc4aSTimo Kreuzer     if (nRptType < 0 || nRptType >= _CRT_ERRCNT)
26004e0dc4aSTimo Kreuzer         return -1;
26104e0dc4aSTimo Kreuzer 
26204e0dc4aSTimo Kreuzer     /*
26304e0dc4aSTimo Kreuzer      * handle the (hopefully rare) case of
26404e0dc4aSTimo Kreuzer      *
26504e0dc4aSTimo Kreuzer      * 1) ASSERT while already dealing with an ASSERT
26604e0dc4aSTimo Kreuzer      *      or
26704e0dc4aSTimo Kreuzer      * 2) two threads asserting at the same time
26804e0dc4aSTimo Kreuzer      */
26904e0dc4aSTimo Kreuzer 
27004e0dc4aSTimo Kreuzer     __try
27104e0dc4aSTimo Kreuzer     {
27204e0dc4aSTimo Kreuzer         if (_CRT_ASSERT == nRptType && _InterlockedIncrement(&_crtAssertBusy) > 0)
27304e0dc4aSTimo Kreuzer         {
27404e0dc4aSTimo Kreuzer             /* use only 'safe' functions -- must not assert in here! */
27504e0dc4aSTimo Kreuzer 
27604e0dc4aSTimo Kreuzer             _ERRCHECK(_itoa_s(nLine, szLineMessage, DBGRPT_MAX_MSG, 10));
27704e0dc4aSTimo Kreuzer 
27804e0dc4aSTimo Kreuzer             __acrt_OutputDebugStringA("Second Chance Assertion Failed: File ");
27904e0dc4aSTimo Kreuzer             __acrt_OutputDebugStringA(szFile ? szFile : "<file unknown>");
28004e0dc4aSTimo Kreuzer             __acrt_OutputDebugStringA(", Line ");
28104e0dc4aSTimo Kreuzer             __acrt_OutputDebugStringA(szLineMessage);
28204e0dc4aSTimo Kreuzer             __acrt_OutputDebugStringA("\n");
28304e0dc4aSTimo Kreuzer 
28404e0dc4aSTimo Kreuzer             _CrtDbgBreak();
28504e0dc4aSTimo Kreuzer             retval=-1;
28604e0dc4aSTimo Kreuzer             __leave;
28704e0dc4aSTimo Kreuzer         }
28804e0dc4aSTimo Kreuzer 
28904e0dc4aSTimo Kreuzer         // Leave space for ASSERTINTRO1 and "\r\n"
29004e0dc4aSTimo Kreuzer         if (szFormat)
29104e0dc4aSTimo Kreuzer         {
29204e0dc4aSTimo Kreuzer             int szlen = 0;
29304e0dc4aSTimo Kreuzer             _ERRCHECK_SPRINTF(szlen = _vsnprintf_s(szUserMessage, DBGRPT_MAX_MSG,
29404e0dc4aSTimo Kreuzer                                                     DBGRPT_MAX_MSG - 2- max(sizeof(ASSERTINTRO1),sizeof(ASSERTINTRO2)),
29504e0dc4aSTimo Kreuzer                                                     szFormat, arglist));
29604e0dc4aSTimo Kreuzer             if (szlen < 0)
29704e0dc4aSTimo Kreuzer             {
29804e0dc4aSTimo Kreuzer                 _ERRCHECK(strcpy_s(szUserMessage, DBGRPT_MAX_MSG, DBGRPT_TOOLONGMSG));
29904e0dc4aSTimo Kreuzer             }
30004e0dc4aSTimo Kreuzer         }
30104e0dc4aSTimo Kreuzer 
30204e0dc4aSTimo Kreuzer         if (_CRT_ASSERT == nRptType)
30304e0dc4aSTimo Kreuzer         {
30404e0dc4aSTimo Kreuzer             _ERRCHECK(strcpy_s(szLineMessage, DBGRPT_MAX_MSG, szFormat ? ASSERTINTRO1 : ASSERTINTRO2));
30504e0dc4aSTimo Kreuzer         }
30604e0dc4aSTimo Kreuzer 
30704e0dc4aSTimo Kreuzer         _ERRCHECK(strcat_s(szLineMessage, DBGRPT_MAX_MSG, szUserMessage));
30804e0dc4aSTimo Kreuzer 
30904e0dc4aSTimo Kreuzer         if (_CRT_ASSERT == nRptType)
31004e0dc4aSTimo Kreuzer         {
31104e0dc4aSTimo Kreuzer             if (_CrtDbgMode[nRptType] & _CRTDBG_MODE_FILE)
31204e0dc4aSTimo Kreuzer             {
31304e0dc4aSTimo Kreuzer                 _ERRCHECK(strcat_s(szLineMessage, DBGRPT_MAX_MSG, "\r"));
31404e0dc4aSTimo Kreuzer             }
31504e0dc4aSTimo Kreuzer 
31604e0dc4aSTimo Kreuzer             _ERRCHECK(strcat_s(szLineMessage, DBGRPT_MAX_MSG, "\n"));
31704e0dc4aSTimo Kreuzer         }
31804e0dc4aSTimo Kreuzer 
31904e0dc4aSTimo Kreuzer         if (szFile)
32004e0dc4aSTimo Kreuzer         {
32104e0dc4aSTimo Kreuzer             int szlen = 0;
32204e0dc4aSTimo Kreuzer             _ERRCHECK_SPRINTF(szlen = _snprintf_s(szOutMessage, DBGRPT_MAX_MSG, DBGRPT_MAX_MSG - 1, "%s(%d) : %s",
32304e0dc4aSTimo Kreuzer                                                     szFile, nLine, szLineMessage));
32404e0dc4aSTimo Kreuzer             if (szlen < 0)
32504e0dc4aSTimo Kreuzer             {
32604e0dc4aSTimo Kreuzer                 _ERRCHECK(strcpy_s(szOutMessage, DBGRPT_MAX_MSG, DBGRPT_TOOLONGMSG));
32704e0dc4aSTimo Kreuzer             }
32804e0dc4aSTimo Kreuzer         }
32904e0dc4aSTimo Kreuzer         else
33004e0dc4aSTimo Kreuzer         {
33104e0dc4aSTimo Kreuzer             _ERRCHECK(strcpy_s(szOutMessage, DBGRPT_MAX_MSG, szLineMessage));
33204e0dc4aSTimo Kreuzer         }
33304e0dc4aSTimo Kreuzer 
33404e0dc4aSTimo Kreuzer         {
33504e0dc4aSTimo Kreuzer             size_t ret = 0;
33604e0dc4aSTimo Kreuzer             errno_t e = 0;
33704e0dc4aSTimo Kreuzer             _ERRCHECK_EINVAL_ERANGE(e = mbstowcs_s(&ret, szOutMessage2, DBGRPT_MAX_MSG, szOutMessage, _TRUNCATE));
33804e0dc4aSTimo Kreuzer             if(e != 0)
33904e0dc4aSTimo Kreuzer             {
34004e0dc4aSTimo Kreuzer                 _ERRCHECK(wcscpy_s(szOutMessage2, DBGRPT_MAX_MSG, _CRT_WIDE(DBGRPT_INVALIDMSG)));
34104e0dc4aSTimo Kreuzer             }
34204e0dc4aSTimo Kreuzer         }
34304e0dc4aSTimo Kreuzer 
34404e0dc4aSTimo Kreuzer         /* User hook may handle report.
34504e0dc4aSTimo Kreuzer             We have to check the ANSI Hook2 List & then the UNICODE Hook2 List.
34604e0dc4aSTimo Kreuzer             Then we have check any ANSI individual Hook set through
34704e0dc4aSTimo Kreuzer             SetReportHook */
34804e0dc4aSTimo Kreuzer 
34904e0dc4aSTimo Kreuzer         if (_pReportHookList || _pReportHookListW)
35004e0dc4aSTimo Kreuzer         {
35104e0dc4aSTimo Kreuzer             __crt_report_hook_node<char> *pnode=nullptr;
35204e0dc4aSTimo Kreuzer             __crt_report_hook_node<wchar_t> *pnodeW=nullptr;
35304e0dc4aSTimo Kreuzer 
35404e0dc4aSTimo Kreuzer             __acrt_lock(__acrt_debug_lock);
35504e0dc4aSTimo Kreuzer             __try
35604e0dc4aSTimo Kreuzer             {
35704e0dc4aSTimo Kreuzer                 for (pnode = _pReportHookList; pnode; pnode = pnode->next)
35804e0dc4aSTimo Kreuzer                 {
35904e0dc4aSTimo Kreuzer                     int hook_retval=0;
36004e0dc4aSTimo Kreuzer                     if (pnode->hook(nRptType, szOutMessage, &hook_retval))
36104e0dc4aSTimo Kreuzer                     {
36204e0dc4aSTimo Kreuzer                         handled=TRUE;
36304e0dc4aSTimo Kreuzer                         retval=hook_retval;
36404e0dc4aSTimo Kreuzer                         __leave;
36504e0dc4aSTimo Kreuzer                     }
36604e0dc4aSTimo Kreuzer                 }
36704e0dc4aSTimo Kreuzer 
36804e0dc4aSTimo Kreuzer                 for (pnodeW = _pReportHookListW; pnodeW; pnodeW = pnodeW->next)
36904e0dc4aSTimo Kreuzer                 {
37004e0dc4aSTimo Kreuzer                     int hook_retval=0;
37104e0dc4aSTimo Kreuzer                     if (pnodeW->hook(nRptType, szOutMessage2, &hook_retval))
37204e0dc4aSTimo Kreuzer                     {
37304e0dc4aSTimo Kreuzer                         handled=TRUE;
37404e0dc4aSTimo Kreuzer                         retval=hook_retval;
37504e0dc4aSTimo Kreuzer                         __leave;
37604e0dc4aSTimo Kreuzer                     }
37704e0dc4aSTimo Kreuzer                 }
37804e0dc4aSTimo Kreuzer             }
37904e0dc4aSTimo Kreuzer             __finally
38004e0dc4aSTimo Kreuzer             {
38104e0dc4aSTimo Kreuzer                 __acrt_unlock(__acrt_debug_lock);
38204e0dc4aSTimo Kreuzer             }
383*e98e9000STimo Kreuzer             __endtry
38404e0dc4aSTimo Kreuzer         }
38504e0dc4aSTimo Kreuzer 
38604e0dc4aSTimo Kreuzer         if (handled)
38704e0dc4aSTimo Kreuzer             __leave;
38804e0dc4aSTimo Kreuzer 
38904e0dc4aSTimo Kreuzer         if (_pfnReportHook)
39004e0dc4aSTimo Kreuzer         {
39104e0dc4aSTimo Kreuzer             int hook_retval=0;
39204e0dc4aSTimo Kreuzer             if (_pfnReportHook(nRptType, szOutMessage, &hook_retval))
39304e0dc4aSTimo Kreuzer             {
39404e0dc4aSTimo Kreuzer                 retval = hook_retval;
39504e0dc4aSTimo Kreuzer                 __leave;
39604e0dc4aSTimo Kreuzer             }
39704e0dc4aSTimo Kreuzer         }
39804e0dc4aSTimo Kreuzer 
39904e0dc4aSTimo Kreuzer         if (_CrtDbgMode[nRptType] & _CRTDBG_MODE_FILE)
40004e0dc4aSTimo Kreuzer         {
40104e0dc4aSTimo Kreuzer             if (_CrtDbgFile[nRptType] != _CRTDBG_INVALID_HFILE)
40204e0dc4aSTimo Kreuzer             {
40304e0dc4aSTimo Kreuzer                 DWORD bytes_written = 0;
40404e0dc4aSTimo Kreuzer                 WriteFile(_CrtDbgFile[nRptType], szOutMessage, static_cast<DWORD>(strlen(szOutMessage)), &bytes_written, nullptr);
40504e0dc4aSTimo Kreuzer             }
40604e0dc4aSTimo Kreuzer         }
40704e0dc4aSTimo Kreuzer 
40804e0dc4aSTimo Kreuzer         if (_CrtDbgMode[nRptType] & _CRTDBG_MODE_DEBUG)
40904e0dc4aSTimo Kreuzer         {
41004e0dc4aSTimo Kreuzer             __acrt_OutputDebugStringA(szOutMessage);
41104e0dc4aSTimo Kreuzer         }
41204e0dc4aSTimo Kreuzer 
41304e0dc4aSTimo Kreuzer         if (_CrtDbgMode[nRptType] & _CRTDBG_MODE_WNDW)
41404e0dc4aSTimo Kreuzer         {
41504e0dc4aSTimo Kreuzer             szLineMessage[0] = 0;
41604e0dc4aSTimo Kreuzer             if (nLine)
41704e0dc4aSTimo Kreuzer             {
41804e0dc4aSTimo Kreuzer                 _ERRCHECK(_itoa_s(nLine, szLineMessage, DBGRPT_MAX_MSG, 10));
41904e0dc4aSTimo Kreuzer             }
42004e0dc4aSTimo Kreuzer 
42104e0dc4aSTimo Kreuzer             retval = __acrt_MessageWindowA(nRptType, returnAddress, szFile, (nLine ? szLineMessage : nullptr), szModule, szUserMessage);
42204e0dc4aSTimo Kreuzer         }
42304e0dc4aSTimo Kreuzer     }
42404e0dc4aSTimo Kreuzer     __finally
42504e0dc4aSTimo Kreuzer     {
42604e0dc4aSTimo Kreuzer         if (_CRT_ASSERT == nRptType)
42704e0dc4aSTimo Kreuzer         {
42804e0dc4aSTimo Kreuzer             _InterlockedDecrement(&_crtAssertBusy);
42904e0dc4aSTimo Kreuzer         }
43004e0dc4aSTimo Kreuzer     }
431*e98e9000STimo Kreuzer     __endtry
43204e0dc4aSTimo Kreuzer 
43304e0dc4aSTimo Kreuzer     return retval;
43404e0dc4aSTimo Kreuzer }
43504e0dc4aSTimo Kreuzer #pragma warning(pop)
43604e0dc4aSTimo Kreuzer 
43704e0dc4aSTimo Kreuzer /***
43804e0dc4aSTimo Kreuzer *int _VCrtDbgReportW() - _CrtDbgReportW calls into this function
43904e0dc4aSTimo Kreuzer *
44004e0dc4aSTimo Kreuzer *Purpose:
44104e0dc4aSTimo Kreuzer *       See remarks for _CrtDbgReport.
44204e0dc4aSTimo Kreuzer *
44304e0dc4aSTimo Kreuzer *Entry:
44404e0dc4aSTimo Kreuzer *       int             nRptType    - report type
44504e0dc4aSTimo Kreuzer *       wchar_t const* szFile      - file name
44604e0dc4aSTimo Kreuzer *       int             nLine       - line number
44704e0dc4aSTimo Kreuzer *       wchar_t const* szModule    - module name
44804e0dc4aSTimo Kreuzer *       wchar_t const* szFormat    - format string
44904e0dc4aSTimo Kreuzer *       va_list         arglist      - var args arglist
45004e0dc4aSTimo Kreuzer *
45104e0dc4aSTimo Kreuzer *Exit:
45204e0dc4aSTimo Kreuzer *       See remarks for _CrtDbgReport
45304e0dc4aSTimo Kreuzer *
45404e0dc4aSTimo Kreuzer *Exceptions:
45504e0dc4aSTimo Kreuzer *
45604e0dc4aSTimo Kreuzer *******************************************************************************/
45704e0dc4aSTimo Kreuzer 
45804e0dc4aSTimo Kreuzer #pragma warning(push)
45904e0dc4aSTimo Kreuzer #pragma warning(disable:6262)
46004e0dc4aSTimo Kreuzer // prefast(6262): This func uses lots of stack because we want to tolerate very large reports, and we can't use malloc here.
_VCrtDbgReportW(int nRptType,void * returnAddress,wchar_t const * szFile,int nLine,wchar_t const * szModule,wchar_t const * szFormat,va_list arglist)46104e0dc4aSTimo Kreuzer int __cdecl _VCrtDbgReportW
46204e0dc4aSTimo Kreuzer (
46304e0dc4aSTimo Kreuzer     int nRptType,
46404e0dc4aSTimo Kreuzer     void * returnAddress,
46504e0dc4aSTimo Kreuzer     wchar_t const* szFile,
46604e0dc4aSTimo Kreuzer     int nLine,
46704e0dc4aSTimo Kreuzer     wchar_t const* szModule,
46804e0dc4aSTimo Kreuzer     wchar_t const* szFormat,
46904e0dc4aSTimo Kreuzer     va_list arglist
47004e0dc4aSTimo Kreuzer     )
47104e0dc4aSTimo Kreuzer {
47204e0dc4aSTimo Kreuzer     int retval=0;
47304e0dc4aSTimo Kreuzer     int handled=FALSE;
47404e0dc4aSTimo Kreuzer     wchar_t szLineMessage[DBGRPT_MAX_MSG] = {0};
47504e0dc4aSTimo Kreuzer     wchar_t szOutMessage[DBGRPT_MAX_MSG] = {0};
47604e0dc4aSTimo Kreuzer     char szOutMessage2[DBGRPT_MAX_MSG] = {0};
47704e0dc4aSTimo Kreuzer     wchar_t szUserMessage[DBGRPT_MAX_MSG] = {0};
47804e0dc4aSTimo Kreuzer 
47904e0dc4aSTimo Kreuzer     if (nRptType < 0 || nRptType >= _CRT_ERRCNT)
48004e0dc4aSTimo Kreuzer         return -1;
48104e0dc4aSTimo Kreuzer 
48204e0dc4aSTimo Kreuzer     /*
48304e0dc4aSTimo Kreuzer      * handle the (hopefully rare) case of
48404e0dc4aSTimo Kreuzer      *
48504e0dc4aSTimo Kreuzer      * 1) ASSERT while already dealing with an ASSERT
48604e0dc4aSTimo Kreuzer      *      or
48704e0dc4aSTimo Kreuzer      * 2) two threads asserting at the same time
48804e0dc4aSTimo Kreuzer      */
48904e0dc4aSTimo Kreuzer 
49004e0dc4aSTimo Kreuzer     __try
49104e0dc4aSTimo Kreuzer     {
49204e0dc4aSTimo Kreuzer         if (_CRT_ASSERT == nRptType && _InterlockedIncrement(&_crtAssertBusy) > 0)
49304e0dc4aSTimo Kreuzer         {
49404e0dc4aSTimo Kreuzer             /* use only 'safe' functions -- must not assert in here! */
49504e0dc4aSTimo Kreuzer 
49604e0dc4aSTimo Kreuzer             _ERRCHECK(_itow_s(nLine, szLineMessage, DBGRPT_MAX_MSG, 10));
49704e0dc4aSTimo Kreuzer 
49804e0dc4aSTimo Kreuzer             OutputDebugStringW(L"Second Chance Assertion Failed: File ");
49904e0dc4aSTimo Kreuzer             OutputDebugStringW(szFile ? szFile : L"<file unknown>");
50004e0dc4aSTimo Kreuzer             OutputDebugStringW(L", Line ");
50104e0dc4aSTimo Kreuzer             OutputDebugStringW(szLineMessage);
50204e0dc4aSTimo Kreuzer             OutputDebugStringW(L"\n");
50304e0dc4aSTimo Kreuzer 
50404e0dc4aSTimo Kreuzer             _CrtDbgBreak();
50504e0dc4aSTimo Kreuzer             retval = -1;
50604e0dc4aSTimo Kreuzer             __leave;
50704e0dc4aSTimo Kreuzer         }
50804e0dc4aSTimo Kreuzer 
50904e0dc4aSTimo Kreuzer         if (szFormat)
51004e0dc4aSTimo Kreuzer         {
51104e0dc4aSTimo Kreuzer             // Leave space for ASSERTINTRO{1,2} and "\r\n"
51204e0dc4aSTimo Kreuzer             size_t const max_assert_intro_count = __max(_countof(ASSERTINTRO1), _countof(ASSERTINTRO2));
51304e0dc4aSTimo Kreuzer             size_t const max_user_message_count = _countof(szUserMessage) - 2 - max_assert_intro_count;
51404e0dc4aSTimo Kreuzer 
51504e0dc4aSTimo Kreuzer             // Force use of the legacy stdio wide character format specifiers
51604e0dc4aSTimo Kreuzer             // mode for source compatibility.  If we ever revisit support for
51704e0dc4aSTimo Kreuzer             // the standard format specifiers, we'll need to revisit this as
51804e0dc4aSTimo Kreuzer             // well.
51904e0dc4aSTimo Kreuzer             int szlen = 0;
52004e0dc4aSTimo Kreuzer             _ERRCHECK_SPRINTF(szlen = __stdio_common_vsnwprintf_s(
52104e0dc4aSTimo Kreuzer                 _CRT_INTERNAL_PRINTF_LEGACY_WIDE_SPECIFIERS,
52204e0dc4aSTimo Kreuzer                 szUserMessage,
52304e0dc4aSTimo Kreuzer                 _countof(szUserMessage),
52404e0dc4aSTimo Kreuzer                 max_user_message_count,
52504e0dc4aSTimo Kreuzer                 szFormat,
52604e0dc4aSTimo Kreuzer                 nullptr,
52704e0dc4aSTimo Kreuzer                 arglist));
52804e0dc4aSTimo Kreuzer             if (szlen < 0)
52904e0dc4aSTimo Kreuzer             {
53004e0dc4aSTimo Kreuzer                 _ERRCHECK(wcscpy_s(szUserMessage, DBGRPT_MAX_MSG, _CRT_WIDE(DBGRPT_TOOLONGMSG)));
53104e0dc4aSTimo Kreuzer             }
53204e0dc4aSTimo Kreuzer         }
53304e0dc4aSTimo Kreuzer 
53404e0dc4aSTimo Kreuzer         if (_CRT_ASSERT == nRptType)
53504e0dc4aSTimo Kreuzer             _ERRCHECK(wcscpy_s(szLineMessage, DBGRPT_MAX_MSG, szFormat ? _CRT_WIDE(ASSERTINTRO1) : _CRT_WIDE(ASSERTINTRO2)));
53604e0dc4aSTimo Kreuzer 
53704e0dc4aSTimo Kreuzer         _ERRCHECK(wcscat_s(szLineMessage, DBGRPT_MAX_MSG, szUserMessage));
53804e0dc4aSTimo Kreuzer 
53904e0dc4aSTimo Kreuzer         if (_CRT_ASSERT == nRptType)
54004e0dc4aSTimo Kreuzer         {
54104e0dc4aSTimo Kreuzer             if (_CrtDbgMode[nRptType] & _CRTDBG_MODE_FILE)
54204e0dc4aSTimo Kreuzer                 _ERRCHECK(wcscat_s(szLineMessage, DBGRPT_MAX_MSG, L"\r"));
54304e0dc4aSTimo Kreuzer             {
54404e0dc4aSTimo Kreuzer                 _ERRCHECK(wcscat_s(szLineMessage, DBGRPT_MAX_MSG, L"\n"));
54504e0dc4aSTimo Kreuzer             }
54604e0dc4aSTimo Kreuzer         }
54704e0dc4aSTimo Kreuzer 
54804e0dc4aSTimo Kreuzer         if (szFile)
54904e0dc4aSTimo Kreuzer         {
55004e0dc4aSTimo Kreuzer             int szlen = 0;
55104e0dc4aSTimo Kreuzer             _ERRCHECK_SPRINTF(szlen = _snwprintf_s(szOutMessage, DBGRPT_MAX_MSG, DBGRPT_MAX_MSG, L"%ls(%d) : %ls",
55204e0dc4aSTimo Kreuzer                                                     szFile, nLine, szLineMessage));
55304e0dc4aSTimo Kreuzer             if (szlen < 0)
55404e0dc4aSTimo Kreuzer                 _ERRCHECK(wcscpy_s(szOutMessage, DBGRPT_MAX_MSG, _CRT_WIDE(DBGRPT_TOOLONGMSG)));
55504e0dc4aSTimo Kreuzer         }
55604e0dc4aSTimo Kreuzer         else
55704e0dc4aSTimo Kreuzer         {
55804e0dc4aSTimo Kreuzer             _ERRCHECK(wcscpy_s(szOutMessage, DBGRPT_MAX_MSG, szLineMessage));
55904e0dc4aSTimo Kreuzer         }
56004e0dc4aSTimo Kreuzer 
56104e0dc4aSTimo Kreuzer         /* scope */
56204e0dc4aSTimo Kreuzer         {
56304e0dc4aSTimo Kreuzer             errno_t e = _ERRCHECK_EINVAL_ERANGE(wcstombs_s(nullptr, szOutMessage2, DBGRPT_MAX_MSG, szOutMessage, _TRUNCATE));
56404e0dc4aSTimo Kreuzer             if(e != 0)
56504e0dc4aSTimo Kreuzer                 _ERRCHECK(strcpy_s(szOutMessage2, DBGRPT_MAX_MSG, DBGRPT_INVALIDMSG));
56604e0dc4aSTimo Kreuzer         }
56704e0dc4aSTimo Kreuzer 
56804e0dc4aSTimo Kreuzer         /* User hook may handle report.
56904e0dc4aSTimo Kreuzer             We have to check the ANSI Hook2 List & then the UNICODE Hook2 List.
57004e0dc4aSTimo Kreuzer             Then we have check any ANSI individual Hook set through
57104e0dc4aSTimo Kreuzer             SetReportHook */
57204e0dc4aSTimo Kreuzer 
57304e0dc4aSTimo Kreuzer         if (_pReportHookList || _pReportHookListW)
57404e0dc4aSTimo Kreuzer         {
57504e0dc4aSTimo Kreuzer             __crt_report_hook_node<char> *pnode=nullptr;
57604e0dc4aSTimo Kreuzer             __crt_report_hook_node<wchar_t> *pnodeW=nullptr;
57704e0dc4aSTimo Kreuzer 
57804e0dc4aSTimo Kreuzer             __acrt_lock(__acrt_debug_lock);
57904e0dc4aSTimo Kreuzer             __try
58004e0dc4aSTimo Kreuzer             {
58104e0dc4aSTimo Kreuzer                 for (pnode = _pReportHookList; pnode; pnode = pnode->next)
58204e0dc4aSTimo Kreuzer                 {
58304e0dc4aSTimo Kreuzer                     int hook_retval=0;
58404e0dc4aSTimo Kreuzer                     if (pnode->hook(nRptType, szOutMessage2, &hook_retval))
58504e0dc4aSTimo Kreuzer                     {
58604e0dc4aSTimo Kreuzer                         retval=hook_retval;
58704e0dc4aSTimo Kreuzer                         handled=TRUE;
58804e0dc4aSTimo Kreuzer                         __leave;
58904e0dc4aSTimo Kreuzer                     }
59004e0dc4aSTimo Kreuzer                 }
59104e0dc4aSTimo Kreuzer 
59204e0dc4aSTimo Kreuzer                 for (pnodeW = _pReportHookListW; pnodeW; pnodeW = pnodeW->next)
59304e0dc4aSTimo Kreuzer                 {
59404e0dc4aSTimo Kreuzer                     int hook_retval=0;
59504e0dc4aSTimo Kreuzer                     if (pnodeW->hook(nRptType, szOutMessage, &hook_retval))
59604e0dc4aSTimo Kreuzer                     {
59704e0dc4aSTimo Kreuzer                         retval=hook_retval;
59804e0dc4aSTimo Kreuzer                         handled=TRUE;
59904e0dc4aSTimo Kreuzer                         __leave;
60004e0dc4aSTimo Kreuzer                     }
60104e0dc4aSTimo Kreuzer                 }
60204e0dc4aSTimo Kreuzer             }
60304e0dc4aSTimo Kreuzer             __finally
60404e0dc4aSTimo Kreuzer             {
60504e0dc4aSTimo Kreuzer                 __acrt_unlock(__acrt_debug_lock);
60604e0dc4aSTimo Kreuzer             }
607*e98e9000STimo Kreuzer             __endtry
60804e0dc4aSTimo Kreuzer         }
60904e0dc4aSTimo Kreuzer 
61004e0dc4aSTimo Kreuzer         if (handled)
61104e0dc4aSTimo Kreuzer             __leave;
61204e0dc4aSTimo Kreuzer 
61304e0dc4aSTimo Kreuzer         if(_pfnReportHook)
61404e0dc4aSTimo Kreuzer         {
61504e0dc4aSTimo Kreuzer             int hook_retval=0;
61604e0dc4aSTimo Kreuzer             if (_pfnReportHook(nRptType, szOutMessage2, &hook_retval))
61704e0dc4aSTimo Kreuzer             {
61804e0dc4aSTimo Kreuzer                 retval = hook_retval;
61904e0dc4aSTimo Kreuzer                 __leave;
62004e0dc4aSTimo Kreuzer             }
62104e0dc4aSTimo Kreuzer         }
62204e0dc4aSTimo Kreuzer 
62304e0dc4aSTimo Kreuzer         if ((_CrtDbgMode[nRptType] & _CRTDBG_MODE_FILE) && _CrtDbgFile[nRptType] != _CRTDBG_INVALID_HFILE)
62404e0dc4aSTimo Kreuzer         {
62504e0dc4aSTimo Kreuzer             /* Use WriteConsole for Consoles, WriteFile otherwise */
62604e0dc4aSTimo Kreuzer             switch (GetFileType(_CrtDbgFile[nRptType]))
62704e0dc4aSTimo Kreuzer             {
62804e0dc4aSTimo Kreuzer             case FILE_TYPE_CHAR:
62904e0dc4aSTimo Kreuzer             {
63004e0dc4aSTimo Kreuzer                 DWORD characters_written = 0;
63104e0dc4aSTimo Kreuzer                 if (WriteConsoleW(_CrtDbgFile[nRptType], szOutMessage, static_cast<DWORD>(wcslen(szOutMessage)), &characters_written, nullptr))
63204e0dc4aSTimo Kreuzer                     break;
63304e0dc4aSTimo Kreuzer 
63404e0dc4aSTimo Kreuzer                 /* If WriteConsole fails & LastError is ERROR_INVALID_VALUE, then the console is redirected */
63504e0dc4aSTimo Kreuzer                 if (GetLastError() != ERROR_INVALID_HANDLE)
63604e0dc4aSTimo Kreuzer                     break;
63704e0dc4aSTimo Kreuzer             }
63804e0dc4aSTimo Kreuzer             default:
63904e0dc4aSTimo Kreuzer             {
64004e0dc4aSTimo Kreuzer                 char szaOutMessage[DBGRPT_MAX_MSG];
64104e0dc4aSTimo Kreuzer                 size_t ret = 0;
64204e0dc4aSTimo Kreuzer                 errno_t e = _ERRCHECK_EINVAL_ERANGE(wcstombs_s(&ret, szaOutMessage, DBGRPT_MAX_MSG, szOutMessage, _TRUNCATE));
64304e0dc4aSTimo Kreuzer 
64404e0dc4aSTimo Kreuzer                 if (e != 0 && e != STRUNCATE)
64504e0dc4aSTimo Kreuzer                 {
64604e0dc4aSTimo Kreuzer                     DWORD bytes_written = 0;
64704e0dc4aSTimo Kreuzer                     WriteFile(_CrtDbgFile[nRptType], szOutMessage, static_cast<DWORD>(wcslen(szOutMessage)) * 2, &bytes_written, nullptr);
64804e0dc4aSTimo Kreuzer                 }
64904e0dc4aSTimo Kreuzer                 else
65004e0dc4aSTimo Kreuzer                 {
65104e0dc4aSTimo Kreuzer                     /* ret counts for the null terminator as well */
65204e0dc4aSTimo Kreuzer                     if (ret > 0)
65304e0dc4aSTimo Kreuzer                     {
65404e0dc4aSTimo Kreuzer                         --ret;
65504e0dc4aSTimo Kreuzer                     }
65604e0dc4aSTimo Kreuzer 
65704e0dc4aSTimo Kreuzer                     DWORD bytes_written = 0;
65804e0dc4aSTimo Kreuzer                     WriteFile(_CrtDbgFile[nRptType], szaOutMessage, static_cast<DWORD>(ret), &bytes_written, nullptr);
65904e0dc4aSTimo Kreuzer                 }
66004e0dc4aSTimo Kreuzer             }
66104e0dc4aSTimo Kreuzer             }
66204e0dc4aSTimo Kreuzer         }
66304e0dc4aSTimo Kreuzer 
66404e0dc4aSTimo Kreuzer         if (_CrtDbgMode[nRptType] & _CRTDBG_MODE_DEBUG)
66504e0dc4aSTimo Kreuzer         {
66604e0dc4aSTimo Kreuzer             ::OutputDebugStringW(szOutMessage);
66704e0dc4aSTimo Kreuzer         }
66804e0dc4aSTimo Kreuzer 
66904e0dc4aSTimo Kreuzer         if (_CrtDbgMode[nRptType] & _CRTDBG_MODE_WNDW)
67004e0dc4aSTimo Kreuzer         {
67104e0dc4aSTimo Kreuzer             szLineMessage[0] = 0;
67204e0dc4aSTimo Kreuzer             if (nLine)
67304e0dc4aSTimo Kreuzer             {
67404e0dc4aSTimo Kreuzer                 _ERRCHECK(_itow_s(nLine, szLineMessage, DBGRPT_MAX_MSG, 10));
67504e0dc4aSTimo Kreuzer             }
67604e0dc4aSTimo Kreuzer             retval = __acrt_MessageWindowW(nRptType, returnAddress, szFile, (nLine ? szLineMessage : nullptr), szModule, szUserMessage);
67704e0dc4aSTimo Kreuzer         }
67804e0dc4aSTimo Kreuzer     }
67904e0dc4aSTimo Kreuzer     __finally
68004e0dc4aSTimo Kreuzer     {
68104e0dc4aSTimo Kreuzer         if (_CRT_ASSERT == nRptType)
68204e0dc4aSTimo Kreuzer         {
68304e0dc4aSTimo Kreuzer             _InterlockedDecrement(&_crtAssertBusy);
68404e0dc4aSTimo Kreuzer         }
68504e0dc4aSTimo Kreuzer     }
686*e98e9000STimo Kreuzer     __endtry
68704e0dc4aSTimo Kreuzer 
68804e0dc4aSTimo Kreuzer     return retval;
68904e0dc4aSTimo Kreuzer }
69004e0dc4aSTimo Kreuzer #pragma warning(pop)
69104e0dc4aSTimo Kreuzer 
69204e0dc4aSTimo Kreuzer } // extern "C"
693