180 lines
5.2 KiB
C
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) */
|