source: trunk/dll/error.c@ 636

Last change on this file since 636 was 636, checked in by Steven Levine, 18 years ago

Add Win_Error_NoMsgBox. Sync others to use common code.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 9.7 KB
Line 
1
2/***********************************************************************
3
4 $Id: error.c 636 2007-04-24 01:08:46Z stevenhl $
5
6 Error reporting
7
8 Copyright (c) 1993-98 M. Kimes
9 Copyright (c) 2004, 2007 Steven H. Levine
10
11 12 Aug 04 SHL Comments
12 23 May 05 SHL Move saymsg here
13 24 May 05 SHL Rename General_Error to more accurate Win_Error
14 24 May 05 SHL Rename saymsg to more accurate Misc_Error
15 24 May 05 SHL Rework Win_Error args and clean up logic
16 27 May 05 SHL Rework to use common showMsg
17 14 Aug 05 SHL showMsg: suppress write to stdout if not error message
18 13 Jul 06 SHL Add Runtime_Error
19 22 Jul 06 SHL Optimize calling sequences
20 26 Jul 06 SHL Add ..._Error2
21 16 Aug 06 SHL Tweak message formatting
22 07 Jan 07 GKY Move error strings etc. to string file
23 18 Apr 07 SHL showMsg: correct selective logging checks
24 19 Apr 07 SHL Add DbgMsg
25 20 Apr 07 SHL Correct IDS_GENERR1TEXT formatting
26 23 Apr 07 SHL Add Win_Error_NoMsgBox. Rework others
27
28***********************************************************************/
29
30#define INCL_DOS
31#define INCL_DOSERRORS
32#define INCL_WIN
33
34#include <os2.h>
35#include <stdlib.h>
36#include <stdio.h>
37#include <string.h>
38#include <stdarg.h>
39
40#include "fm3dll.h"
41#include "fm3str.h"
42
43#pragma data_seg(DATA1)
44#pragma alloc_text(FMINPUT,Win_Error,Dos_Error,saymsg,showMsg)
45
46static VOID formatWinError(PSZ pszBuf, UINT cBufBytes, HWND hwndErr, HWND hwndOwner,
47 PCSZ pszSrcFile, UINT uSrcLineNo,
48 PCSZ pszFmt, va_list pva);
49
50static APIRET showMsg(ULONG mb_type, HWND hwnd, PCSZ pszTitle, PCSZ pszMsg, BOOL wantLog);
51
52//=== DbgMsg: output debug message stderr ===
53
54VOID DbgMsg(PCSZ pszSrcFile, UINT uSrcLineNo, PCSZ pszFmt, ...)
55{
56 va_list va;
57
58 // OK for source file name to be null
59 fprintf(stderr, "%s %u", pszSrcFile ? pszSrcFile : "n/a", uSrcLineNo);
60 // If format null want just file and line
61 if (pszFmt) {
62 fputc(' ', stderr);
63 va_start(va, pszFmt);
64 vfprintf(stderr, pszFmt, va);
65 va_end(va);
66 }
67 fputc('\n', stderr);
68 fflush(stderr);
69
70} // DbgMsg
71
72//== Dos_Error: report Dos...() error using passed message string ===
73
74INT Dos_Error(ULONG mb_type, ULONG ulRC, HWND hwndOwner,
75 PCSZ pszSrcFile, UINT uSrcLineNo, PCSZ pszFmt, ...)
76{
77 CHAR szMsg[4096];
78 ULONG Class; // Error class
79 ULONG action; // Error action
80 ULONG Locus; // Error location
81 ULONG ulMsgLen;
82 CHAR *pszMsgStart;
83 CHAR *psz;
84 va_list va;
85
86 if (!ulRC)
87 return MBID_ENTER; // Should not have been called
88
89 // Format caller's message
90 va_start(va, pszFmt);
91 szMsg[sizeof(szMsg) - 1] = 0;
92 vsprintf(szMsg, pszFmt, va);
93 va_end(va);
94
95 if (szMsg[sizeof(szMsg) - 1]) {
96 fprintf(stderr, "Buffer overflow in Dos_Error - need %u bytes\n", strlen(szMsg) + 1);
97 fflush(stderr);
98 }
99
100 if (strchr(szMsg, ' ') == NULL)
101 strcat(szMsg, " failed"); // Assume simple function name
102
103 DosErrClass(ulRC, &Class, &action, &Locus);
104
105 sprintf(szMsg + strlen(szMsg),
106 GetPString(IDS_DOSERR1TEXT),
107 pszSrcFile,
108 uSrcLineNo,
109 ulRC,
110 GetPString(IDS_ERRCLASS1TEXT + (Class - 1)),
111 GetPString(IDS_ERRACTION1TEXT + (action - 1)),
112 GetPString(IDS_ERRLOCUS1TEXT + (Locus - 1)));
113 pszMsgStart = szMsg + strlen(szMsg) + 1;
114 // Get message leaving space for NL separator
115 if (!DosGetMessage
116 (NULL, 0L, (PCHAR) pszMsgStart + 1, 1024, ulRC, "OSO001.MSG", &ulMsgLen)
117 || !DosGetMessage(NULL, 0L, (PCHAR) pszMsgStart + 1, 1024, ulRC,
118 "OSO001H.MSG", &ulMsgLen)) {
119 // Got message
120 pszMsgStart[ulMsgLen + 1] = 0; // Terminate
121 *(pszMsgStart - 1) = '\n'; // Stuff NL before message text
122 *pszMsgStart = '\"'; // Prefix message text with quote
123
124 psz = pszMsgStart + ulMsgLen; // Point at last char
125 // Chop trailing NL CR TAB
126 while (*psz &&
127 (*psz == '\r' || *psz == '\n' || *psz == ' ' || *psz == '\t')) {
128 *psz-- = 0;
129 }
130 strcat(psz, "\""); // Append trailing quote
131
132 // Convert CR and NL combos to single space
133 psz = pszMsgStart;
134 while (*psz) {
135 if (*psz == '\n' || *psz == '\r') {
136 while (*(psz + 1) == '\n' || *(psz + 1) == '\r')
137 memmove(psz, psz + 1, strlen(psz));
138 *psz = ' ';
139 }
140 else
141 psz++;
142 }
143 }
144
145 return showMsg(mb_type | MB_ICONEXCLAMATION, hwndOwner, GetPString(IDS_DOSERR2TEXT),
146 szMsg, TRUE);
147
148} // Dos_Error
149
150//== Dos_Error2: report Dos...() error using passed message id ===
151
152INT Dos_Error2(ULONG mb_type, ULONG ulRC, HWND hwndOwner,
153 PCSZ pszSrcFile, UINT uSrcLineNo, UINT idMsg)
154{
155 return Dos_Error(mb_type, ulRC, hwndOwner, pszSrcFile, uSrcLineNo,
156 GetPString(idMsg));
157} // Dos_Error2
158
159/**
160 * Format last PM error into passed buffer
161 */
162
163static VOID formatWinError(PSZ pszBuf, UINT cBufBytes,
164 HWND hwndErr, HWND hwndOwner,
165 PCSZ pszSrcFile, UINT uSrcLineNo,
166 PCSZ pszFmt, va_list pva)
167{
168 PERRINFO pErrInfoBlk; /* Pointer to ERRINFO structure filled
169 by WinGetErrorInfo */
170 PSZ pszOffset; /* Pointer to current error message returned
171 by WinGetErrorInfo */
172 PSZ psz;
173 HAB hab;
174
175 if (hwndErr == NULLHANDLE)
176 hab = (HAB)0;
177 else
178 hab = WinQueryAnchorBlock(hwndErr);
179
180 // Format callers message
181 pszBuf[cBufBytes - 1] = 0;
182 vsprintf(pszBuf, pszFmt, pva);
183
184 if (pszBuf[cBufBytes - 1]) {
185 fprintf(stderr, "Buffer overflow in formatWinError - need %u bytes\n", strlen(pszBuf) + 1);
186 fflush(stderr);
187 }
188
189 if (strchr(pszBuf, ' ') == NULL)
190 strcat(pszBuf, " failed"); // Assume simple function name
191
192 // Append file name and line number and trailing space
193 sprintf(pszBuf + strlen(pszBuf),
194 GetPString(IDS_GENERR1TEXT), pszSrcFile, uSrcLineNo);
195
196 // Get last PM error for the current thread
197 pErrInfoBlk = WinGetErrorInfo(hab);
198 if (!pErrInfoBlk) {
199 psz = pszBuf + strlen(pszBuf);
200 strcpy(psz, "WinGetErrorInfo failed");
201 }
202 else {
203 if (!hwndOwner)
204 hwndOwner = HWND_DESKTOP;
205 /* Find message offset in array of message offsets
206 Assume 1 message - fixme?
207 */
208 pszOffset = ((PSZ) pErrInfoBlk) + pErrInfoBlk->offaoffszMsg;
209 /* Address error message in array of messages and
210 append error message to source code linenumber
211 */
212 psz = pszBuf + strlen(pszBuf);
213 sprintf(psz, "#0x%04x \"", ERRORIDERROR(pErrInfoBlk->idError));
214 psz += strlen(psz);
215 strcpy(psz, ((PSZ) pErrInfoBlk) + *(PSHORT) pszOffset);
216 psz += strlen(psz);
217 // Chop trailing mush
218 psz--;
219 while (*psz == '\r' || *psz == '\n' || *psz == ' ')
220 *psz-- = 0;
221 if (*psz)
222 psz++;
223 strcpy(psz, "\"");
224 WinFreeErrorInfo(pErrInfoBlk); // Free resource segment
225 }
226
227} // formatWinError
228
229//== Runtime_Error: report runtime library error using passed message string ===
230
231VOID Runtime_Error(PCSZ pszSrcFile, UINT uSrcLineNo, PCSZ pszFmt, ...)
232{
233 CHAR szMsg[4096];
234 va_list va;
235 PSZ psz;
236
237 // Format caller's message
238 va_start(va, pszFmt);
239 szMsg[sizeof(szMsg) - 1] = 0;
240 vsprintf(szMsg, pszFmt, va);
241 va_end(va);
242
243 if (szMsg[sizeof(szMsg) - 1]) {
244 fprintf(stderr, "Buffer overflow in Runtime_Error - need %u bytes\n", strlen(szMsg) + 1);
245 fflush(stderr);
246 }
247
248 if (strchr(szMsg, ' ') == NULL)
249 strcat(szMsg, " failed"); // Assume simple function name
250
251 sprintf(szMsg + strlen(szMsg),
252 GetPString(IDS_GENERR1TEXT), pszSrcFile, uSrcLineNo);
253
254 showMsg(MB_ICONEXCLAMATION, HWND_DESKTOP, DEBUG_STRING, szMsg, TRUE);
255
256} // Runtime_Error
257
258//== Runtime_Error2: report runtime library error using passed message id ===
259
260VOID Runtime_Error2(PCSZ pszSrcFile, UINT uSrcLineNo, UINT idMsg)
261{
262 Runtime_Error(pszSrcFile, uSrcLineNo, GetPString(idMsg));
263
264} // Runtime_Error2
265
266// fixme to be rename to Misc_Error
267
268//=== saymsg: report misc error using passed message ===
269
270APIRET saymsg(ULONG mb_type, HWND hwnd, PCSZ pszTitle, PCSZ pszFmt, ...)
271{
272 CHAR szMsg[4096];
273 va_list va;
274
275 va_start(va, pszFmt);
276 szMsg[sizeof(szMsg) - 1] = 0;
277 vsprintf(szMsg, pszFmt, va);
278 va_end(va);
279
280 if (szMsg[sizeof(szMsg) - 1]) {
281 fprintf(stderr, "Buffer overflow in saymsg - need %u bytes\n", strlen(szMsg) + 1);
282 fflush(stderr);
283 }
284
285 return showMsg(mb_type, hwnd, pszTitle, szMsg, FALSE);
286
287} // saymsg
288
289//=== showMsg: display error popup ===
290
291static APIRET showMsg(ULONG mb_type, HWND hwndOwner,
292 PCSZ pszTitle, PCSZ pszMsg, BOOL wantLog)
293{
294 if (wantLog) {
295 fputs(pszMsg, stderr);
296 fputc('\n', stderr);
297 fputc('\n', stderr);
298 fflush(stderr);
299 }
300
301 if (!hwndOwner)
302 hwndOwner = HWND_DESKTOP;
303
304 DosBeep(250, 100);
305
306 return WinMessageBox(HWND_DESKTOP, // Parent
307 hwndOwner,
308 (PSZ) pszMsg, (PSZ) pszTitle, 0, // help id
309 mb_type | MB_MOVEABLE);
310} // showMsg
311
312//== Win_Error: report Win...() error using passed message string ===
313
314VOID Win_Error(HWND hwndErr, HWND hwndOwner,
315 PCSZ pszSrcFile, UINT uSrcLineNo,
316 PCSZ pszFmt, ...)
317{
318 CHAR szMsg[4096];
319 PSZ psz;
320 HAB hab;
321 va_list va;
322
323 // Format callers message
324 va_start(va, pszFmt);
325 formatWinError(szMsg, sizeof(szMsg), hwndErr, hwndOwner, pszSrcFile, uSrcLineNo, pszFmt, va);
326 va_end(va);
327
328 showMsg(MB_ENTER | MB_ICONEXCLAMATION, hwndOwner, GetPString(IDS_GENERR2TEXT),
329 szMsg, TRUE);
330
331} // Win_Error
332
333//== Win_Error2: report Win...() error using passed message id ===
334
335VOID Win_Error2(HWND hwndErr, HWND hwndOwner,
336 PCSZ pszSrcFile, UINT uSrcLineNo, UINT idMsg)
337{
338 Win_Error(hwndErr, hwndOwner, pszSrcFile, uSrcLineNo, GetPString(idMsg));
339
340} // Win_Error2
341
342/**
343 * Output PM error messsage to stderr
344 * This does to same reporting as Win_Error, but bypasses the
345 * message box popup.
346 * Use this version when the popup would hang PM.
347 */
348
349VOID Win_Error_NoMsgBox(HWND hwndErr, HWND hwndOwner,
350 PCSZ pszSrcFile, UINT uSrcLineNo, PCSZ pszFmt, ...)
351{
352 CHAR szMsg[4096];
353 va_list va;
354
355 // Format callers message
356 va_start(va, pszFmt);
357 formatWinError(szMsg, sizeof(szMsg), hwndErr, hwndOwner, pszSrcFile, uSrcLineNo, pszFmt, va);
358 va_end(va);
359
360 fputs(szMsg, stderr);
361 fputc('\n', stderr);
362 fputc('\n', stderr);
363 fflush(stderr);
364
365 DosBeep(250, 100);
366
367} // Win_Error_NoMsgBox
Note: See TracBrowser for help on using the repository browser.