mirror of
https://github.com/reactos/reactos.git
synced 2025-08-07 05:43:08 +00:00
[UCRT] Import Microsoft.Windows.SDK.CRTSource version 10.0.22621.3
Imported from https://www.nuget.org/packages/Microsoft.Windows.SDK.CRTSource/10.0.22621.3 License: MIT
This commit is contained in:
parent
f1b60c66f0
commit
04e0dc4a7a
568 changed files with 115483 additions and 0 deletions
688
sdk/lib/ucrt/misc/dbgrptt.cpp
Normal file
688
sdk/lib/ucrt/misc/dbgrptt.cpp
Normal file
|
@ -0,0 +1,688 @@
|
|||
/***
|
||||
*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);
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
return retval;
|
||||
}
|
||||
#pragma warning(pop)
|
||||
|
||||
} // extern "C"
|
Loading…
Add table
Add a link
Reference in a new issue