/*** *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 #include /* * 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, ""); 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) */