windows-nt/Source/XPSP1/NT/base/crts/crtw32/misc/seclocf.c
2020-09-26 16:20:57 +08:00

180 lines
5.2 KiB
C

/***
*seclocf.c - Report /GS security check failure, local system CRT version
*
* Copyright (c) 2000-2001, Microsoft Corporation. All rights reserved.
*
*Purpose:
* Define function used to report a security check failure. This
* version is only used when linking against the system CRT DLL,
* msvcrt.dll (or msvcrtd.dll). If that DLL does not export the global
* failure handler __security_error_handler, then a default local
* handler is used instead.
*
* This version does not use any other CRT functions, so it can be used
* to compile code /GS which does not want to use the CRT.
*
* Entrypoints:
* __local_security_error_handler
*
*Revision History:
* 01-24-00 PML Created.
* 08-30-00 PML Rename handlers, add extra parameters. Extensively
* rework, moving the GetProcAddress of
* __security_error_handler from seccook.c to here.
* 03-28-01 PML Protect against GetModuleFileName overflow (vs7#231284)
*
*******************************************************************************/
#if defined(_SYSCRT) && defined(CRTDLL)
#include <windows.h>
#include <stdlib.h>
/*
* Default messagebox string components
*/
#define PROGINTRO "Program: "
#define DOTDOTDOT "..."
#define BOXINTRO_0 "Unknown security failure detected!"
#define MSGTEXT_0 \
"A security error of unknown cause has been detected which has\n" \
"corrupted the program's internal state. The program cannot safely\n" \
"continue execution and must now be terminated.\n"
#define BOXINTRO_1 "Buffer overrun detected!"
#define MSGTEXT_1 \
"A buffer overrun has been detected which has corrupted the program's\n" \
"internal state. The program cannot safely continue execution and must\n"\
"now be terminated.\n"
#define MAXLINELEN 60 /* max length for line in message box */
/***
*__local_security_error_handler() - Report security error
*
*Purpose:
* A /GS security error has been detected, and the global failure handler
* is not available from msvcrt.dll. Pop up a message box and terminate
* the program.
*
*Entry:
* int code - security failure code
* void *data - code-specific data
*
*Exit:
* Calls ExitProcess.
*
*Exceptions:
*
*******************************************************************************/
void __cdecl __local_security_error_handler(
int code,
void *data)
{
char progname[MAX_PATH + 1];
char * pch;
char * outmsg;
char * boxintro;
char * msgtext;
size_t subtextlen;
HANDLE hCRT;
_secerr_handler_func pfnSecErrorHandler;
HANDLE hUser32;
int (APIENTRY *pfnMessageBoxA)(HWND, LPCSTR, LPCSTR, UINT);
/*
* Check if the system CRT DLL implements the process-wide security
* failure handler, and use it instead if available.
*/
#ifdef _DEBUG
hCRT = GetModuleHandle("msvcrtd.dll");
#else
hCRT = GetModuleHandle("msvcrt.dll");
#endif
if (hCRT != NULL) {
pfnSecErrorHandler = (_secerr_handler_func)
GetProcAddress(hCRT, "__security_error_handler");
if (pfnSecErrorHandler != NULL) {
pfnSecErrorHandler(code, data);
ExitProcess(3);
}
}
/*
* DLL-resident handler not available. Use a local version that just
* pops up a message box.
*/
switch (code) {
default:
/*
* Unknown failure code, which probably means an older CRT is
* being used with a newer compiler.
*/
boxintro = BOXINTRO_0;
msgtext = MSGTEXT_0;
subtextlen = sizeof(BOXINTRO_0) + sizeof(MSGTEXT_0);
break;
case _SECERR_BUFFER_OVERRUN:
/*
* Buffer overrun detected which may have overwritten a return
* address.
*/
boxintro = BOXINTRO_1;
msgtext = MSGTEXT_1;
subtextlen = sizeof(BOXINTRO_1) + sizeof(MSGTEXT_1);
break;
}
progname[MAX_PATH] = '\0';
if (!GetModuleFileName(NULL, progname, MAX_PATH))
lstrcpy(progname, "<program name unknown>");
pch = progname;
/* sizeof(PROGINTRO) includes the NULL terminator */
if (sizeof(PROGINTRO) + lstrlen(progname) + 1 > MAXLINELEN)
{
pch += (sizeof(PROGINTRO) + lstrlen(progname) + 1) - MAXLINELEN;
CopyMemory(pch, DOTDOTDOT, sizeof(DOTDOTDOT) - 1);
}
outmsg = (char *)_alloca(subtextlen - 1 + 2
+ sizeof(PROGINTRO) - 1
+ lstrlen(pch)
+ 2);
lstrcpy(outmsg, boxintro);
lstrcat(outmsg, "\n\n");
lstrcat(outmsg, PROGINTRO);
lstrcat(outmsg, pch);
lstrcat(outmsg, "\n\n");
lstrcat(outmsg, msgtext);
hUser32 = LoadLibrary("user32.dll");
if (hUser32 != NULL) {
pfnMessageBoxA = (int (APIENTRY *)(HWND, LPCSTR, LPCSTR, UINT))
GetProcAddress(hUser32, "MessageBoxA");
if (pfnMessageBoxA != NULL) {
pfnMessageBoxA(
NULL,
outmsg,
"Microsoft Visual C++ Runtime Library",
MB_OK|MB_ICONHAND|MB_SETFOREGROUND|MB_TASKMODAL);
}
FreeLibrary(hUser32);
}
ExitProcess(3);
}
#endif /* defined(_SYSCRT) && defined(CRTDLL) */