source: trunk/dll/errutil.c@ 1402

Last change on this file since 1402 was 1402, checked in by Gregg Young, 16 years ago

Remove variable aurgs from docopy & unlinkf (not used); Move more strings to PCSZs and string table; Move PCSZs to compile time initialization; Fix hang on startup caused by a drive scan and a dircnr scan trying to update a drive in the tree at the same time (related to the "treeswitch options); Code cleanup mainly removal of old printfs, SayMsgs, DbgMsg and unneeded %s.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 11.0 KB
Line 
1
2/***********************************************************************
3
4 $Id: errutil.c 1402 2009-03-14 17:17:59Z gyoung $
5
6 Error reporting
7
8 Copyright (c) 1993-98 M. Kimes
9 Copyright (c) 2004, 2008 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 14 Aug 07 SHL Add GetMSecTimer
28 14 Aug 07 SHL Use GetMSecTimer in DbgMsg
29 05 Jan 08 SHL Renamed from error.c to match errutil.h
30 18 Dec 08 SHL Show thread id in DbgMsg
31 07 Feb 09 GKY Allow user to turn off alert and/or error beeps in settings notebook.
32 07 Feb 09 GKY Eliminate Win_Error2 by moving function names to PCSZs used in Win_Error
33 07 Feb 09 GKY Allow user to turn off alert and/or error beeps in settings notebook.
34 08 Mar 09 GKY Remove Dos_Error2 (unused) and Runtime_Error2 (no advantage over using Runtime_Error)
35
36***********************************************************************/
37
38#include <stdio.h>
39#include <string.h>
40#include <stdarg.h>
41
42#define INCL_DOS
43#define INCL_WIN
44#define INCL_DOSERRORS
45#define INCL_DOSPROCESS // PPIB PTIB
46#define INCL_LONGLONG
47
48#include "errutil.h"
49#include "strutil.h" // GetPString
50#include "fm3str.h"
51#include "notebook.h" // fErrorBeepOff
52#include "init.h" // Data declares
53
54#pragma data_seg(DATA1)
55
56static PSZ pszSrcFile = __FILE__;
57
58static VOID formatWinError(PSZ pszBuf, UINT cBufBytes, HWND hwndErr, HWND hwndOwner,
59 PCSZ pszSrcFile, UINT uSrcLineNo,
60 PCSZ pszFmt, va_list pva);
61
62static APIRET showMsg(ULONG mb_type, HWND hwnd, PCSZ pszTitle, PCSZ pszMsg, BOOL wantLog);
63
64//=== DbgMsg: output debug message stderr ===
65
66VOID DbgMsg(PCSZ pszSrcFile, UINT uSrcLineNo, PCSZ pszFmt, ...)
67{
68 PIB *ppib;
69 TIB *ptib;
70 ULONG ultid;
71 APIRET apiret;
72 va_list va;
73
74#if 1 // fixme to be selectable
75
76 static ULONG ul1stMSec;
77 // static ULONG ulLastMSec;
78
79 ULONG msec = GetMSecTimer();
80 ULONG delta;
81
82 if (!ul1stMSec) {
83 ul1stMSec = msec;
84 // ulLastMSec = msec; // Avoid big delta 1st time
85 }
86
87 delta = msec - ul1stMSec;
88 // ulLastMSec = msec;
89 fprintf(stderr, "%03lu.%03lu ", delta / 1000, delta % 1000);
90
91#endif
92
93 apiret = DosGetInfoBlocks(&ptib, &ppib);
94 if (apiret)
95 ultid = 0;
96 else
97 ultid = ptib->tib_ptib2->tib2_ultid;
98
99 // OK for source file name to be null
100 fprintf(stderr, "%s %u (%lu)", pszSrcFile ? pszSrcFile : "n/a", uSrcLineNo, ultid);
101 // If format null want just file and line
102 if (pszFmt) {
103 fputc(' ', stderr);
104 va_start(va, pszFmt);
105 vfprintf(stderr, pszFmt, va);
106 va_end(va);
107 }
108 fputc('\n', stderr);
109 fflush(stderr);
110
111} // DbgMsg
112
113//== Dos_Error: report Dos...() error using passed message string ===
114
115INT Dos_Error(ULONG mb_type, ULONG ulRC, HWND hwndOwner,
116 PCSZ pszSrcFile, UINT uSrcLineNo, PCSZ pszFmt, ...)
117{
118 CHAR szMsg[4096];
119 ULONG Class; // Error class
120 ULONG action; // Error action
121 ULONG Locus; // Error location
122 ULONG ulMsgLen;
123 CHAR *pszMsgStart;
124 CHAR *psz;
125 va_list va;
126
127 if (!ulRC)
128 return MBID_ENTER; // Should not have been called
129
130 // Format caller's message
131 va_start(va, pszFmt);
132 szMsg[sizeof(szMsg) - 1] = 0;
133 vsprintf(szMsg, pszFmt, va);
134 va_end(va);
135
136 if (szMsg[sizeof(szMsg) - 1]) {
137 fprintf(stderr, "Buffer overflow in Dos_Error - need %u bytes\n", strlen(szMsg) + 1);
138 fflush(stderr);
139 }
140
141 if (strchr(szMsg, ' ') == NULL) {
142 strcat(szMsg, " ");
143 strcat(szMsg, GetPString(IDS_FAILEDTEXT)); // Assume simple function name
144 }
145
146 DosErrClass(ulRC, &Class, &action, &Locus);
147
148 sprintf(szMsg + strlen(szMsg),
149 GetPString(IDS_DOSERR1TEXT),
150 pszSrcFile,
151 uSrcLineNo,
152 ulRC,
153 GetPString(IDS_ERRCLASS1TEXT + (Class - 1)),
154 GetPString(IDS_ERRACTION1TEXT + (action - 1)),
155 GetPString(IDS_ERRLOCUS1TEXT + (Locus - 1)));
156 pszMsgStart = szMsg + strlen(szMsg) + 1;
157 // Get message leaving space for NL separator
158 if (!DosGetMessage
159 (NULL, 0L, (PCHAR) pszMsgStart + 1, 1024, ulRC, "OSO001.MSG", &ulMsgLen)
160 || !DosGetMessage(NULL, 0L, (PCHAR) pszMsgStart + 1, 1024, ulRC,
161 "OSO001H.MSG", &ulMsgLen)) {
162 // Got message
163 pszMsgStart[ulMsgLen + 1] = 0; // Terminate
164 *(pszMsgStart - 1) = '\n'; // Stuff NL before message text
165 *pszMsgStart = '\"'; // Prefix message text with quote
166
167 psz = pszMsgStart + ulMsgLen; // Point at last char
168 // Chop trailing NL CR TAB
169 while (*psz &&
170 (*psz == '\r' || *psz == '\n' || *psz == ' ' || *psz == '\t')) {
171 *psz-- = 0;
172 }
173 strcat(psz, "\""); // Append trailing quote
174
175 // Convert CR and NL combos to single space
176 psz = pszMsgStart;
177 while (*psz) {
178 if (*psz == '\n' || *psz == '\r') {
179 while (*(psz + 1) == '\n' || *(psz + 1) == '\r')
180 memmove(psz, psz + 1, strlen(psz));
181 *psz = ' ';
182 }
183 else
184 psz++;
185 }
186 }
187
188 return showMsg(mb_type | MB_ICONEXCLAMATION, hwndOwner, GetPString(IDS_DOSERR2TEXT),
189 szMsg, TRUE);
190
191} // Dos_Error
192
193/**
194 * Format last PM error into passed buffer
195 */
196
197static VOID formatWinError(PSZ pszBuf, UINT cBufBytes,
198 HWND hwndErr, HWND hwndOwner,
199 PCSZ pszSrcFile, UINT uSrcLineNo,
200 PCSZ pszFmt, va_list pva)
201{
202 PERRINFO pErrInfoBlk; /* Pointer to ERRINFO structure filled
203 by WinGetErrorInfo */
204 PSZ pszOffset; /* Pointer to current error message returned
205 by WinGetErrorInfo */
206 PSZ psz;
207 HAB hab;
208
209 if (hwndErr == NULLHANDLE)
210 hab = (HAB)0;
211 else
212 hab = WinQueryAnchorBlock(hwndErr);
213
214 // Format callers message
215 pszBuf[cBufBytes - 1] = 0;
216 vsprintf(pszBuf, pszFmt, pva);
217
218 if (pszBuf[cBufBytes - 1]) {
219 fprintf(stderr, "Buffer overflow in formatWinError - need %u bytes\n", strlen(pszBuf) + 1);
220 fflush(stderr);
221 }
222
223 if (strchr(pszBuf, ' ') == NULL) {
224 strcat(pszBuf, " ");
225 strcat(pszBuf, GetPString(IDS_FAILEDTEXT)); // Assume simple function name
226 }
227
228 // Append file name and line number and trailing space
229 sprintf(pszBuf + strlen(pszBuf),
230 GetPString(IDS_GENERR1TEXT), pszSrcFile, uSrcLineNo);
231
232 // Get last PM error for the current thread
233 pErrInfoBlk = WinGetErrorInfo(hab);
234 if (!pErrInfoBlk) {
235 ERRORID id = WinGetLastError(hab);
236 psz = pszBuf + strlen(pszBuf);
237 sprintf(psz, " WinGetErrorInfo failed (%u)", id);
238 }
239 else {
240 if (!hwndOwner)
241 hwndOwner = HWND_DESKTOP;
242 /* Find message offset in array of message offsets
243 Assume 1 message - fixme?
244 */
245 pszOffset = ((PSZ) pErrInfoBlk) + pErrInfoBlk->offaoffszMsg;
246 /* Address error message in array of messages and
247 append error message to source code linenumber
248 */
249 psz = pszBuf + strlen(pszBuf);
250 sprintf(psz, " #0x%04x \"", ERRORIDERROR(pErrInfoBlk->idError));
251 psz += strlen(psz);
252 strcpy(psz, ((PSZ) pErrInfoBlk) + *(PSHORT) pszOffset);
253 psz += strlen(psz);
254 // Chop trailing mush
255 psz--;
256 while (*psz == '\r' || *psz == '\n' || *psz == ' ')
257 *psz-- = 0;
258 if (*psz)
259 psz++;
260 strcpy(psz, "\"");
261 WinFreeErrorInfo(pErrInfoBlk); // Free resource segment
262 }
263
264} // formatWinError
265
266/**
267 * Return millisecond timer value
268 * Resolution is milliseconds, but accuracy will be less
269 * depending on systems settings
270 */
271
272ULONG GetMSecTimer(void)
273{
274 ULONG msec;
275
276 APIRET rc = DosQuerySysInfo(QSV_MS_COUNT, QSV_MS_COUNT,
277 &msec, sizeof(msec));
278 if (rc) {
279 Dos_Error(MB_ENTER, rc, HWND_DESKTOP, pszSrcFile, __LINE__,
280 "DosQuerySysInfo");
281 msec = 0;
282 }
283 return msec;
284}
285
286//== Runtime_Error: report runtime library error using passed message string ===
287//If pszFmt is NULL a No Data error message is returned GKY 20 Feb 09 (Replaces Runtime_Error2)
288
289VOID Runtime_Error(PCSZ pszSrcFile, UINT uSrcLineNo, PCSZ pszFmt, ...)
290{
291 CHAR szMsg[4096];
292 va_list va;
293
294 // Format caller's message
295 if (!pszFmt)
296 pszFmt = PCSZ_NODATA;
297 va_start(va, pszFmt);
298 szMsg[sizeof(szMsg) - 1] = 0;
299 vsprintf(szMsg, pszFmt, va);
300 va_end(va);
301
302 if (szMsg[sizeof(szMsg) - 1]) {
303 fprintf(stderr, "Buffer overflow in Runtime_Error - need %u bytes\n", strlen(szMsg) + 1);
304 fflush(stderr);
305 }
306
307 if (strchr(szMsg, ' ') == NULL) {
308 strcat(szMsg, " ");
309 strcat(szMsg, GetPString(IDS_FAILEDTEXT)); // Assume simple function name
310 }
311
312 sprintf(szMsg + strlen(szMsg),
313 GetPString(IDS_GENERR1TEXT), pszSrcFile, uSrcLineNo);
314
315 showMsg(MB_ICONEXCLAMATION, HWND_DESKTOP, GetPString(IDS_DEBUG_STRING), szMsg, TRUE);
316
317} // Runtime_Error
318
319//=== saymsg: report misc error using passed message ===
320
321APIRET saymsg(ULONG mb_type, HWND hwnd, PCSZ pszTitle, PCSZ pszFmt, ...)
322{
323 CHAR szMsg[4096];
324 va_list va;
325
326 va_start(va, pszFmt);
327 szMsg[sizeof(szMsg) - 1] = 0;
328 vsprintf(szMsg, pszFmt, va);
329 va_end(va);
330
331 if (szMsg[sizeof(szMsg) - 1]) {
332 fprintf(stderr, "Buffer overflow in saymsg - need %u bytes\n", strlen(szMsg) + 1);
333 fflush(stderr);
334 }
335
336 return showMsg(mb_type, hwnd, pszTitle, szMsg, FALSE);
337
338} // saymsg
339
340//=== showMsg: display error popup ===
341
342static APIRET showMsg(ULONG mb_type, HWND hwndOwner,
343 PCSZ pszTitle, PCSZ pszMsg, BOOL wantLog)
344{
345 if (wantLog) {
346 fputs(pszMsg, stderr);
347 fputc('\n', stderr);
348 fputc('\n', stderr);
349 fflush(stderr);
350 }
351
352 if (!hwndOwner)
353 hwndOwner = HWND_DESKTOP;
354 if (!fErrorBeepOff)
355 DosBeep(250, 100);
356
357 return WinMessageBox(HWND_DESKTOP, // Parent
358 hwndOwner,
359 (PSZ) pszMsg, (PSZ) pszTitle, 0, // help id
360 mb_type | MB_MOVEABLE);
361} // showMsg
362
363//== Win_Error: report Win...() error using passed message string ===
364
365VOID Win_Error(HWND hwndErr, HWND hwndOwner,
366 PCSZ pszSrcFile, UINT uSrcLineNo,
367 PCSZ pszFmt, ...)
368{
369 CHAR szMsg[4096];
370 va_list va;
371
372 // Format callers message
373 va_start(va, pszFmt);
374 formatWinError(szMsg, sizeof(szMsg), hwndErr, hwndOwner, pszSrcFile, uSrcLineNo, pszFmt, va);
375 va_end(va);
376
377 showMsg(MB_ENTER | MB_ICONEXCLAMATION, hwndOwner, GetPString(IDS_GENERR2TEXT),
378 szMsg, TRUE);
379
380} // Win_Error
381
382/**
383 * Output PM error messsage to stderr
384 * This does to same reporting as Win_Error, but bypasses the
385 * message box popup.
386 * Use this version when the popup would hang PM.
387 */
388
389VOID Win_Error_NoMsgBox(HWND hwndErr, HWND hwndOwner,
390 PCSZ pszSrcFile, UINT uSrcLineNo, PCSZ pszFmt, ...)
391{
392 CHAR szMsg[4096];
393 va_list va;
394
395 // Format callers message
396 va_start(va, pszFmt);
397 formatWinError(szMsg, sizeof(szMsg), hwndErr, hwndOwner, pszSrcFile, uSrcLineNo, pszFmt, va);
398 va_end(va);
399
400 fputs(szMsg, stderr);
401 fputc('\n', stderr);
402 fputc('\n', stderr);
403 fflush(stderr);
404 if (!fErrorBeepOff)
405 DosBeep(250, 100);
406
407} // Win_Error_NoMsgBox
408
409#pragma alloc_text(ERROR,Win_Error,Dos_Error,saymsg,showMsg,Runtime_Error,GetMSecTimer)
Note: See TracBrowser for help on using the repository browser.