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
RevLine 
[121]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
[907]9 Copyright (c) 2004, 2008 Steven H. Levine
[121]10
[137]11 12 Aug 04 SHL Comments
12 23 May 05 SHL Move saymsg here
[144]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
[182]16 27 May 05 SHL Rework to use common showMsg
[258]17 14 Aug 05 SHL showMsg: suppress write to stdout if not error message
[327]18 13 Jul 06 SHL Add Runtime_Error
19 22 Jul 06 SHL Optimize calling sequences
[383]20 26 Jul 06 SHL Add ..._Error2
[452]21 16 Aug 06 SHL Tweak message formatting
[552]22 07 Jan 07 GKY Move error strings etc. to string file
[613]23 18 Apr 07 SHL showMsg: correct selective logging checks
[616]24 19 Apr 07 SHL Add DbgMsg
25 20 Apr 07 SHL Correct IDS_GENERR1TEXT formatting
[636]26 23 Apr 07 SHL Add Win_Error_NoMsgBox. Rework others
[787]27 14 Aug 07 SHL Add GetMSecTimer
28 14 Aug 07 SHL Use GetMSecTimer in DbgMsg
[907]29 05 Jan 08 SHL Renamed from error.c to match errutil.h
[1373]30 18 Dec 08 SHL Show thread id in DbgMsg
[1395]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.
[1402]34 08 Mar 09 GKY Remove Dos_Error2 (unused) and Runtime_Error2 (no advantage over using Runtime_Error)
[121]35
36***********************************************************************/
37
[907]38#include <stdio.h>
39#include <string.h>
40#include <stdarg.h>
41
[2]42#define INCL_DOS
[1373]43#define INCL_WIN
[2]44#define INCL_DOSERRORS
[1373]45#define INCL_DOSPROCESS // PPIB PTIB
[1395]46#define INCL_LONGLONG
[2]47
[907]48#include "errutil.h"
49#include "strutil.h" // GetPString
[2]50#include "fm3str.h"
[1395]51#include "notebook.h" // fErrorBeepOff
[1398]52#include "init.h" // Data declares
[2]53
54#pragma data_seg(DATA1)
55
[787]56static PSZ pszSrcFile = __FILE__;
57
[636]58static VOID formatWinError(PSZ pszBuf, UINT cBufBytes, HWND hwndErr, HWND hwndOwner,
59 PCSZ pszSrcFile, UINT uSrcLineNo,
60 PCSZ pszFmt, va_list pva);
61
[613]62static APIRET showMsg(ULONG mb_type, HWND hwnd, PCSZ pszTitle, PCSZ pszMsg, BOOL wantLog);
[2]63
[636]64//=== DbgMsg: output debug message stderr ===
[144]65
[636]66VOID DbgMsg(PCSZ pszSrcFile, UINT uSrcLineNo, PCSZ pszFmt, ...)
[121]67{
[1373]68 PIB *ppib;
69 TIB *ptib;
70 ULONG ultid;
71 APIRET apiret;
[144]72 va_list va;
[2]73
[787]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
[1373]93 apiret = DosGetInfoBlocks(&ptib, &ppib);
94 if (apiret)
95 ultid = 0;
96 else
97 ultid = ptib->tib_ptib2->tib2_ultid;
98
[636]99 // OK for source file name to be null
[1373]100 fprintf(stderr, "%s %u (%lu)", pszSrcFile ? pszSrcFile : "n/a", uSrcLineNo, ultid);
[636]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);
[613]107 }
[636]108 fputc('\n', stderr);
109 fflush(stderr);
[613]110
[636]111} // DbgMsg
[327]112
[452]113//== Dos_Error: report Dos...() error using passed message string ===
[144]114
[636]115INT Dos_Error(ULONG mb_type, ULONG ulRC, HWND hwndOwner,
116 PCSZ pszSrcFile, UINT uSrcLineNo, PCSZ pszFmt, ...)
[121]117{
[182]118 CHAR szMsg[4096];
[636]119 ULONG Class; // Error class
120 ULONG action; // Error action
121 ULONG Locus; // Error location
[144]122 ULONG ulMsgLen;
123 CHAR *pszMsgStart;
124 CHAR *psz;
125 va_list va;
[2]126
[144]127 if (!ulRC)
128 return MBID_ENTER; // Should not have been called
[121]129
[144]130 // Format caller's message
131 va_start(va, pszFmt);
[613]132 szMsg[sizeof(szMsg) - 1] = 0;
[182]133 vsprintf(szMsg, pszFmt, va);
[144]134 va_end(va);
[121]135
[613]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
[1395]141 if (strchr(szMsg, ' ') == NULL) {
142 strcat(szMsg, " ");
143 strcat(szMsg, GetPString(IDS_FAILEDTEXT)); // Assume simple function name
144 }
[327]145
[144]146 DosErrClass(ulRC, &Class, &action, &Locus);
147
[182]148 sprintf(szMsg + strlen(szMsg),
[144]149 GetPString(IDS_DOSERR1TEXT),
[636]150 pszSrcFile,
151 uSrcLineNo,
[144]152 ulRC,
153 GetPString(IDS_ERRCLASS1TEXT + (Class - 1)),
154 GetPString(IDS_ERRACTION1TEXT + (action - 1)),
155 GetPString(IDS_ERRLOCUS1TEXT + (Locus - 1)));
[182]156 pszMsgStart = szMsg + strlen(szMsg) + 1;
[144]157 // Get message leaving space for NL separator
[551]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)) {
[144]162 // Got message
163 pszMsgStart[ulMsgLen + 1] = 0; // Terminate
[182]164 *(pszMsgStart - 1) = '\n'; // Stuff NL before message text
[144]165 *pszMsgStart = '\"'; // Prefix message text with quote
[182]166
[144]167 psz = pszMsgStart + ulMsgLen; // Point at last char
168 // Chop trailing NL CR TAB
169 while (*psz &&
[551]170 (*psz == '\r' || *psz == '\n' || *psz == ' ' || *psz == '\t')) {
[144]171 *psz-- = 0;
172 }
173 strcat(psz, "\""); // Append trailing quote
174
175 // Convert CR and NL combos to single space
176 psz = pszMsgStart;
[551]177 while (*psz) {
178 if (*psz == '\n' || *psz == '\r') {
[144]179 while (*(psz + 1) == '\n' || *(psz + 1) == '\r')
180 memmove(psz, psz + 1, strlen(psz));
181 *psz = ' ';
[2]182 }
[144]183 else
184 psz++;
[2]185 }
186 }
[137]187
[613]188 return showMsg(mb_type | MB_ICONEXCLAMATION, hwndOwner, GetPString(IDS_DOSERR2TEXT),
189 szMsg, TRUE);
[137]190
[636]191} // Dos_Error
[137]192
[636]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
[1395]223 if (strchr(pszBuf, ' ') == NULL) {
224 strcat(pszBuf, " ");
225 strcat(pszBuf, GetPString(IDS_FAILEDTEXT)); // Assume simple function name
226 }
[636]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) {
[907]235 ERRORID id = WinGetLastError(hab);
[636]236 psz = pszBuf + strlen(pszBuf);
[904]237 sprintf(psz, " WinGetErrorInfo failed (%u)", id);
[636]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);
[904]250 sprintf(psz, " #0x%04x \"", ERRORIDERROR(pErrInfoBlk->idError));
[636]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
[787]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
[452]286//== Runtime_Error: report runtime library error using passed message string ===
[1398]287//If pszFmt is NULL a No Data error message is returned GKY 20 Feb 09 (Replaces Runtime_Error2)
[327]288
[551]289VOID Runtime_Error(PCSZ pszSrcFile, UINT uSrcLineNo, PCSZ pszFmt, ...)
[327]290{
291 CHAR szMsg[4096];
292 va_list va;
293
294 // Format caller's message
[1398]295 if (!pszFmt)
296 pszFmt = PCSZ_NODATA;
[327]297 va_start(va, pszFmt);
[613]298 szMsg[sizeof(szMsg) - 1] = 0;
[327]299 vsprintf(szMsg, pszFmt, va);
300 va_end(va);
301
[613]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
[1395]307 if (strchr(szMsg, ' ') == NULL) {
308 strcat(szMsg, " ");
309 strcat(szMsg, GetPString(IDS_FAILEDTEXT)); // Assume simple function name
310 }
[327]311
312 sprintf(szMsg + strlen(szMsg),
[613]313 GetPString(IDS_GENERR1TEXT), pszSrcFile, uSrcLineNo);
[327]314
[1395]315 showMsg(MB_ICONEXCLAMATION, HWND_DESKTOP, GetPString(IDS_DEBUG_STRING), szMsg, TRUE);
[327]316
[636]317} // Runtime_Error
[327]318
[452]319//=== saymsg: report misc error using passed message ===
[144]320
[551]321APIRET saymsg(ULONG mb_type, HWND hwnd, PCSZ pszTitle, PCSZ pszFmt, ...)
[137]322{
[182]323 CHAR szMsg[4096];
[144]324 va_list va;
[137]325
[144]326 va_start(va, pszFmt);
[613]327 szMsg[sizeof(szMsg) - 1] = 0;
[182]328 vsprintf(szMsg, pszFmt, va);
[144]329 va_end(va);
330
[613]331 if (szMsg[sizeof(szMsg) - 1]) {
332 fprintf(stderr, "Buffer overflow in saymsg - need %u bytes\n", strlen(szMsg) + 1);
333 fflush(stderr);
334 }
[452]335
[613]336 return showMsg(mb_type, hwnd, pszTitle, szMsg, FALSE);
337
[636]338} // saymsg
[182]339
[452]340//=== showMsg: display error popup ===
[182]341
[636]342static APIRET showMsg(ULONG mb_type, HWND hwndOwner,
343 PCSZ pszTitle, PCSZ pszMsg, BOOL wantLog)
[182]344{
[613]345 if (wantLog) {
[258]346 fputs(pszMsg, stderr);
347 fputc('\n', stderr);
[614]348 fputc('\n', stderr);
[258]349 fflush(stderr);
350 }
351
[616]352 if (!hwndOwner)
353 hwndOwner = HWND_DESKTOP;
[1395]354 if (!fErrorBeepOff)
355 DosBeep(250, 100);
[144]356
[182]357 return WinMessageBox(HWND_DESKTOP, // Parent
[616]358 hwndOwner,
[551]359 (PSZ) pszMsg, (PSZ) pszTitle, 0, // help id
[182]360 mb_type | MB_MOVEABLE);
[613]361} // showMsg
[616]362
[636]363//== Win_Error: report Win...() error using passed message string ===
[616]364
[636]365VOID Win_Error(HWND hwndErr, HWND hwndOwner,
366 PCSZ pszSrcFile, UINT uSrcLineNo,
367 PCSZ pszFmt, ...)
[616]368{
[636]369 CHAR szMsg[4096];
[616]370 va_list va;
371
[636]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);
[616]401 fputc('\n', stderr);
[636]402 fputc('\n', stderr);
[616]403 fflush(stderr);
[1395]404 if (!fErrorBeepOff)
405 DosBeep(250, 100);
[616]406
[636]407} // Win_Error_NoMsgBox
[787]408
[1402]409#pragma alloc_text(ERROR,Win_Error,Dos_Error,saymsg,showMsg,Runtime_Error,GetMSecTimer)
Note: See TracBrowser for help on using the repository browser.