Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

335 lines
9.8 KiB

  1. /***
  2. *crt0msg.c - startup error messages
  3. *
  4. * Copyright (c) 1989-2001, Microsoft Corporation. All rights reserved.
  5. *
  6. *Purpose:
  7. * Prints out banner for runtime error messages.
  8. *
  9. *Revision History:
  10. * 06-27-89 PHG Module created, based on asm version
  11. * 04-09-90 GJF Added #include <cruntime.h>. Made calling type
  12. * _CALLTYPE1. Also, fixed the copyright.
  13. * 04-10-90 GJF Fixed compiler warnings (-W3).
  14. * 06-04-90 GJF Revised to be more compatible with old scheme.
  15. * nmsghdr.c merged in.
  16. * 10-08-90 GJF New-style function declarators.
  17. * 10-11-90 GJF Added _RT_ABORT, _RT_FLOAT, _RT_HEAP.
  18. * 12-04-90 SRW Changed to include <oscalls.h> instead of <doscalls.h>
  19. * 12-06-90 SRW Added _CRUISER_ and _WIN32 conditionals.
  20. * 02-04-91 SRW Changed to call WriteFile (_WIN32_)
  21. * 02-25-91 MHL Adapt to ReadFile/WriteFile changes (_WIN32_)
  22. * 04-10-91 PNT Added _MAC_ conditional
  23. * 09-09-91 GJF Added _RT_ONEXIT error.
  24. * 09-18-91 GJF Added 3 math errors, also corrected comments for
  25. * errors that were changed in rterr.h, cmsgs.h.
  26. * 03-31-92 DJM POSIX support.
  27. * 10-23-92 GJF Added _RT_PUREVIRT.
  28. * 04-05-93 JWM Added _GET_RTERRMSG().
  29. * 04-06-93 SKS Replace _CRTAPI* with __cdecl
  30. * 04-29-93 GJF Removed rterrs[] entries for _RT_STACK, _RT_INTDIV,
  31. * _RT_NONCONT and _RT_INVALDISP.
  32. * 09-06-94 CFW Remove Cruiser support.
  33. * 09-06-94 GJF Revised to use MessageBox for GUI apps.
  34. * 01-10-95 JCF Remove __app_type and __error_mode check for _MAC_.
  35. * 02-14-95 CFW write -> _write, error messages to debug reporting.
  36. * 02-15-95 CFW Make all CRT message boxes look alike.
  37. * 02-24-95 CFW Use __crtMessageBoxA.
  38. * 02-27-95 CFW Change __crtMessageBoxA params.
  39. * 03-07-95 GJF Added _RT_STDIOINIT.
  40. * 03-21-95 CFW Add _CRT_ASSERT report type.
  41. * 06-06-95 CFW Remove _MB_SERVICE_NOTIFICATION.
  42. * 06-19-95 CFW Avoid STDIO calls.
  43. * 06-20-95 GJF Added _RT_LOWIOINIT.
  44. * 04-23-96 GJF Added _RT_HEAPINIT. Also, revised _NMSG_WRITE to
  45. * allow for ioinit() having not been invoked.
  46. * 05-05-97 GJF Changed call to WriteFile, in _NMSG_WRITE, so that
  47. * it does not reference _pioinfo. Also, a few cosmetic
  48. * changes.
  49. * 01-04-99 GJF Changes for 64-bit size_t.
  50. * 05-17-99 PML Remove all Macintosh support.
  51. * 01-24-99 PML Fix buffer overrun in _NMSG_WRITE.
  52. * 05-10-00 GB Fix call of _CrtDbgReport for _RT_BANNER in _NMSG_WRITE
  53. * 03-28-01 PML Protect against GetModuleFileName overflow (vs7#231284)
  54. *
  55. *******************************************************************************/
  56. #include <cruntime.h>
  57. #include <internal.h>
  58. #include <stddef.h>
  59. #include <stdlib.h>
  60. #include <stdio.h>
  61. #include <string.h>
  62. #include <rterr.h>
  63. #include <cmsgs.h>
  64. #include <awint.h>
  65. #include <windows.h>
  66. #include <dbgint.h>
  67. #ifdef _POSIX_
  68. #include <posix\sys\types.h>
  69. #include <posix\unistd.h>
  70. #endif
  71. /* struct used to lookup and access runtime error messages */
  72. struct rterrmsgs {
  73. int rterrno; /* error number */
  74. char *rterrtxt; /* text of error message */
  75. };
  76. /* runtime error messages */
  77. static struct rterrmsgs rterrs[] = {
  78. /* 2 */
  79. { _RT_FLOAT, _RT_FLOAT_TXT },
  80. /* 8 */
  81. { _RT_SPACEARG, _RT_SPACEARG_TXT },
  82. /* 9 */
  83. { _RT_SPACEENV, _RT_SPACEENV_TXT },
  84. /* 10 */
  85. { _RT_ABORT, _RT_ABORT_TXT },
  86. /* 16 */
  87. { _RT_THREAD, _RT_THREAD_TXT },
  88. /* 17 */
  89. { _RT_LOCK, _RT_LOCK_TXT },
  90. /* 18 */
  91. { _RT_HEAP, _RT_HEAP_TXT },
  92. /* 19 */
  93. { _RT_OPENCON, _RT_OPENCON_TXT },
  94. /* 22 */
  95. /* { _RT_NONCONT, _RT_NONCONT_TXT }, */
  96. /* 23 */
  97. /* { _RT_INVALDISP, _RT_INVALDISP_TXT }, */
  98. /* 24 */
  99. { _RT_ONEXIT, _RT_ONEXIT_TXT },
  100. /* 25 */
  101. { _RT_PUREVIRT, _RT_PUREVIRT_TXT },
  102. /* 26 */
  103. { _RT_STDIOINIT, _RT_STDIOINIT_TXT },
  104. /* 27 */
  105. { _RT_LOWIOINIT, _RT_LOWIOINIT_TXT },
  106. /* 28 */
  107. { _RT_HEAPINIT, _RT_HEAPINIT_TXT },
  108. /* 120 */
  109. { _RT_DOMAIN, _RT_DOMAIN_TXT },
  110. /* 121 */
  111. { _RT_SING, _RT_SING_TXT },
  112. /* 122 */
  113. { _RT_TLOSS, _RT_TLOSS_TXT },
  114. /* 252 */
  115. { _RT_CRNL, _RT_CRNL_TXT },
  116. /* 255 */
  117. { _RT_BANNER, _RT_BANNER_TXT }
  118. };
  119. /* number of elements in rterrs[] */
  120. #define _RTERRCNT ( sizeof(rterrs) / sizeof(struct rterrmsgs) )
  121. /* For C, _FF_DBGMSG is inactive, so _adbgmsg is
  122. set to null
  123. For FORTRAN, _adbgmsg is set to point to
  124. _FF_DBGMSG in dbginit initializer in dbgmsg.asm */
  125. void (*_adbgmsg)(void) = NULL;
  126. /***
  127. *_FF_MSGBANNER - writes out first part of run-time error messages
  128. *
  129. *Purpose:
  130. * This routine writes "\r\nrun-time error " to standard error.
  131. *
  132. * For FORTRAN $DEBUG error messages, it also uses the _FF_DBGMSG
  133. * routine whose address is stored in the _adbgmsg variable to print out
  134. * file and line number information associated with the run-time error.
  135. * If the value of _adbgmsg is found to be null, then the _FF_DBGMSG
  136. * routine won't be called from here (the case for C-only programs).
  137. *
  138. *Entry:
  139. * No arguments.
  140. *
  141. *Exit:
  142. * Nothing returned.
  143. *
  144. *Exceptions:
  145. * None handled.
  146. *
  147. *******************************************************************************/
  148. void __cdecl _FF_MSGBANNER (
  149. void
  150. )
  151. {
  152. if ( (__error_mode == _OUT_TO_STDERR) || ((__error_mode ==
  153. _OUT_TO_DEFAULT) && (__app_type == _CONSOLE_APP)) )
  154. {
  155. _NMSG_WRITE(_RT_CRNL); /* new line to begin error message */
  156. if (_adbgmsg != 0)
  157. _adbgmsg(); /* call __FF_DBGMSG for FORTRAN */
  158. _NMSG_WRITE(_RT_BANNER); /* run-time error message banner */
  159. }
  160. }
  161. /***
  162. *__NMSGWRITE(message) - write a given message to handle 2 (stderr)
  163. *
  164. *Purpose:
  165. * This routine writes the message associated with rterrnum
  166. * to stderr.
  167. *
  168. *Entry:
  169. * int rterrnum - runtime error number
  170. *
  171. *Exit:
  172. * no return value
  173. *
  174. *Exceptions:
  175. * none
  176. *
  177. *******************************************************************************/
  178. void __cdecl _NMSG_WRITE (
  179. int rterrnum
  180. )
  181. {
  182. int tblindx;
  183. #if !defined(_POSIX_)
  184. DWORD bytes_written; /* bytes written */
  185. #endif
  186. for ( tblindx = 0 ; tblindx < _RTERRCNT ; tblindx++ )
  187. if ( rterrnum == rterrs[tblindx].rterrno )
  188. break;
  189. if ( rterrnum == rterrs[tblindx].rterrno )
  190. {
  191. #ifdef _DEBUG
  192. /*
  193. * Report error.
  194. *
  195. * If _CRT_ERROR has _CRTDBG_REPORT_WNDW on, and user chooses
  196. * "Retry", call the debugger.
  197. *
  198. * Otherwise, continue execution.
  199. *
  200. */
  201. if (rterrnum != _RT_CRNL && rterrnum != _RT_BANNER)
  202. {
  203. if (1 == _CrtDbgReport(_CRT_ERROR, NULL, 0, NULL, rterrs[tblindx].rterrtxt))
  204. _CrtDbgBreak();
  205. }
  206. #endif
  207. #if !defined(_POSIX_)
  208. if ( (__error_mode == _OUT_TO_STDERR) || ((__error_mode ==
  209. _OUT_TO_DEFAULT) && (__app_type == _CONSOLE_APP)) )
  210. {
  211. WriteFile( GetStdHandle(STD_ERROR_HANDLE),
  212. rterrs[tblindx].rterrtxt,
  213. (unsigned long)strlen(rterrs[tblindx].rterrtxt),
  214. &bytes_written,
  215. NULL );
  216. }
  217. else if (rterrnum != _RT_CRNL)
  218. {
  219. #define MAXLINELEN 60
  220. char * pch;
  221. char progname[MAX_PATH + 1];
  222. char * outmsg;
  223. progname[MAX_PATH] = '\0';
  224. if (!GetModuleFileName(NULL, progname, MAX_PATH))
  225. strcpy(progname, "<program name unknown>");
  226. pch = (char *)progname;
  227. if (strlen(pch) + 1 > MAXLINELEN)
  228. {
  229. pch += strlen(progname) + 1 - MAXLINELEN;
  230. strncpy(pch, "...", 3);
  231. }
  232. #define MSGTEXTPREFIX "Runtime Error!\n\nProgram: "
  233. outmsg = (char *)_alloca(sizeof(MSGTEXTPREFIX)
  234. + strlen(pch)
  235. + 2
  236. + strlen(rterrs[tblindx].rterrtxt));
  237. strcpy(outmsg, MSGTEXTPREFIX);
  238. strcat(outmsg, pch);
  239. strcat(outmsg, "\n\n");
  240. strcat(outmsg, rterrs[tblindx].rterrtxt);
  241. __crtMessageBoxA(outmsg,
  242. "Microsoft Visual C++ Runtime Library",
  243. MB_OK|MB_ICONHAND|MB_SETFOREGROUND|MB_TASKMODAL);
  244. }
  245. #else /* !_POSIX_ */
  246. write(STDERR_FILENO,rterrs[tblindx].rterrtxt,
  247. strlen(rterrs[tblindx].rterrtxt));
  248. #endif /* !_POSIX_ */
  249. }
  250. }
  251. /***
  252. *_GET_RTERRMSG(message) - returns ptr to error text for given runtime error
  253. *
  254. *Purpose:
  255. * This routine returns the message associated with rterrnum
  256. *
  257. *Entry:
  258. * int rterrnum - runtime error number
  259. *
  260. *Exit:
  261. * no return value
  262. *
  263. *Exceptions:
  264. * none
  265. *
  266. *******************************************************************************/
  267. char * __cdecl _GET_RTERRMSG (
  268. int rterrnum
  269. )
  270. {
  271. int tblindx;
  272. for ( tblindx = 0 ; tblindx < _RTERRCNT ; tblindx++ )
  273. if ( rterrnum == rterrs[tblindx].rterrno )
  274. break;
  275. if ( rterrnum == rterrs[tblindx].rterrno )
  276. return rterrs[tblindx].rterrtxt;
  277. else
  278. return NULL;
  279. }