1 | /* SCCSID = %W% %E% */
|
---|
2 | /****************************************************************************
|
---|
3 | * *
|
---|
4 | * Copyright (c) IBM Corporation 1994 - 1997. *
|
---|
5 | * *
|
---|
6 | * The following IBM OS/2 source code is provided to you solely for the *
|
---|
7 | * the purpose of assisting you in your development of OS/2 device drivers. *
|
---|
8 | * You may use this code in accordance with the IBM License Agreement *
|
---|
9 | * provided in the IBM Device Driver Source Kit for OS/2. *
|
---|
10 | * *
|
---|
11 | ****************************************************************************/
|
---|
12 | /**@internal %W%
|
---|
13 | * Facilities for logging errors, status, and realtime traces. Logged
|
---|
14 | * information can be routed to any combination of display, COM: lines,
|
---|
15 | * system trace buffer (retrieved by TRACEFMT utility), and/or system
|
---|
16 | * error log.
|
---|
17 | * @version %I%
|
---|
18 | * @context 16-bit, Ring 3 or Ring 0, DD Ioctl time context. The BINARYLOG
|
---|
19 | * and PERFLOG methods may be used in Interrupt context.
|
---|
20 | * @notes
|
---|
21 | *
|
---|
22 | * Supported syntax for data formatting (case insensitive)
|
---|
23 | *
|
---|
24 | * >--- % --+-----+--------------- B -+---|
|
---|
25 | * | | | |
|
---|
26 | * +- 0 -+ +----------- Q -+
|
---|
27 | * | |
|
---|
28 | * +-----+---+- D -+
|
---|
29 | * | | | |
|
---|
30 | * +- L -+ +- X -+
|
---|
31 | *
|
---|
32 | * Where
|
---|
33 | * 0 - format with leading 0's
|
---|
34 | * L - long integer
|
---|
35 | * D - format decimal
|
---|
36 | * X - format hexidecimal
|
---|
37 | * B - byte hex (BINARY logs only)
|
---|
38 | * Q - quadword hex (BINARY logs only)
|
---|
39 | * Not supported at this time
|
---|
40 | * S - ASCIIZ data
|
---|
41 | *
|
---|
42 | * @notes bugs
|
---|
43 | * The %b, %q, and %b datatypes are not implemented across all log types.
|
---|
44 | *
|
---|
45 | * @history
|
---|
46 | */
|
---|
47 |
|
---|
48 | extern "C" {
|
---|
49 | #define INCL_NOPMAPI
|
---|
50 | #define INCL_DOSMISC
|
---|
51 | #include <os2.h>
|
---|
52 | }
|
---|
53 |
|
---|
54 | #include <devhelp.h>
|
---|
55 | #include <string.h> // strlen() intrinsic
|
---|
56 | #include "iodelay.h"
|
---|
57 | #include "log.hpp"
|
---|
58 | #include <include.h>
|
---|
59 |
|
---|
60 | #define CR 0x0d
|
---|
61 | #define LF 0x0a
|
---|
62 |
|
---|
63 | #define LEADING_ZEROES 0x8000
|
---|
64 | #define SIGNIFICANT_FIELD 0x0007
|
---|
65 |
|
---|
66 | #define UART_DATA 0x00 // UART Data port
|
---|
67 | #define UART_INT_ENAB 0x01 // UART Interrupt enable
|
---|
68 | #define UART_INT_ID 0x02 // interrupt ID
|
---|
69 | #define UART_LINE_CTRL 0x03 // line control registers
|
---|
70 | #define UART_MODEM_CTRL 0x04 // modem control register
|
---|
71 | #define UART_LINE_STAT 0x05 // line status register
|
---|
72 | #define UART_MODEM_STAT 0x06 // modem status regiser
|
---|
73 | #define UART_DIVISOR_LO 0x00 // divisor latch least sig
|
---|
74 | #define UART_DIVISOR_HI 0x01h // divisor latch most sig
|
---|
75 |
|
---|
76 | // Global logging variables. Values are setup in init.cpp.
|
---|
77 | LOG* pStatus; // Points to the status log.
|
---|
78 | LOG* pError; // Points to the error log.
|
---|
79 | LOG* pSoftError; // Points to the error log.
|
---|
80 | BINARYLOG* pTrace; // Points to the trace log.
|
---|
81 | PERFLOG* pPerfLog; // Points to Performance trace log.
|
---|
82 |
|
---|
83 | // Used to convert binary to ascii
|
---|
84 | static const char ddhextab[]="0123456789ABCDEF";
|
---|
85 |
|
---|
86 |
|
---|
87 | //----------- ddprintf_DecWordToASCII -
|
---|
88 | PSZ LOG::_DecWordToASCII(PSZ StrPtr, WORD wDecVal, WORD Option)
|
---|
89 | /*
|
---|
90 | ; StrPtr - Output, pointer to location to save resulting ASCII string.
|
---|
91 | ; wDecVal - Input, 16 bit value to convert.
|
---|
92 | ; Option - Input, selects leading zeros.
|
---|
93 | */
|
---|
94 | {
|
---|
95 | BOOL fNonZero=FALSE;
|
---|
96 | WORD Digit;
|
---|
97 | WORD Power=10000;
|
---|
98 |
|
---|
99 | while (Power)
|
---|
100 | {
|
---|
101 | Digit=0;
|
---|
102 | while (wDecVal >=Power) //Digit=wDecVal/Power;
|
---|
103 | {
|
---|
104 | Digit++;
|
---|
105 | wDecVal-=Power;
|
---|
106 | }
|
---|
107 |
|
---|
108 | if (Digit)
|
---|
109 | fNonZero=TRUE;
|
---|
110 |
|
---|
111 | if (Digit ||
|
---|
112 | fNonZero ||
|
---|
113 | (Option & LEADING_ZEROES) ||
|
---|
114 | ((Power==1) && (fNonZero==FALSE)))
|
---|
115 | {
|
---|
116 | *StrPtr=(char)('0'+Digit);
|
---|
117 | StrPtr++;
|
---|
118 | }
|
---|
119 |
|
---|
120 | if (Power==10000)
|
---|
121 | Power=1000;
|
---|
122 | else if (Power==1000)
|
---|
123 | Power=100;
|
---|
124 | else if (Power==100)
|
---|
125 | Power=10;
|
---|
126 | else if (Power==10)
|
---|
127 | Power=1;
|
---|
128 | else
|
---|
129 | Power=0;
|
---|
130 | } // end while
|
---|
131 |
|
---|
132 | return (StrPtr);
|
---|
133 | }
|
---|
134 |
|
---|
135 | //----------- ddprintf_DecLongToASCII -
|
---|
136 | PSZ LOG::_DecLongToASCII(PSZ StrPtr, DWORD lDecVal,WORD Option)
|
---|
137 | {
|
---|
138 | BOOL fNonZero=FALSE;
|
---|
139 | DWORD Digit;
|
---|
140 | DWORD Power=1000000000; // 1 billion
|
---|
141 |
|
---|
142 | while (Power)
|
---|
143 | {
|
---|
144 | Digit=0; // Digit=lDecVal/Power
|
---|
145 | while (lDecVal >=Power) // replaced with while loop
|
---|
146 | {
|
---|
147 | Digit++;
|
---|
148 | lDecVal-=Power;
|
---|
149 | }
|
---|
150 |
|
---|
151 | if (Digit)
|
---|
152 | fNonZero=TRUE;
|
---|
153 |
|
---|
154 | if (Digit ||
|
---|
155 | fNonZero ||
|
---|
156 | (Option & LEADING_ZEROES) ||
|
---|
157 | ((Power==1) && (fNonZero==FALSE)))
|
---|
158 | {
|
---|
159 | *StrPtr=(char)('0'+Digit);
|
---|
160 | StrPtr++;
|
---|
161 | }
|
---|
162 |
|
---|
163 | if (Power==1000000000) // 1 billion
|
---|
164 | Power=100000000;
|
---|
165 | else if (Power==100000000)
|
---|
166 | Power=10000000;
|
---|
167 | else if (Power==10000000)
|
---|
168 | Power=1000000;
|
---|
169 | else if (Power==1000000)
|
---|
170 | Power=100000;
|
---|
171 | else if (Power==100000)
|
---|
172 | Power=10000;
|
---|
173 | else if (Power==10000)
|
---|
174 | Power=1000;
|
---|
175 | else if (Power==1000)
|
---|
176 | Power=100;
|
---|
177 | else if (Power==100)
|
---|
178 | Power=10;
|
---|
179 | else if (Power==10)
|
---|
180 | Power=1;
|
---|
181 | else
|
---|
182 | Power=0;
|
---|
183 | }
|
---|
184 | return (StrPtr);
|
---|
185 | }
|
---|
186 | //----------- ddprintf_HexWordToASCII -
|
---|
187 | PSZ LOG::_HexWordToASCII(PSZ StrPtr, WORD wHexVal, WORD Option)
|
---|
188 | {
|
---|
189 | BOOL fNonZero=FALSE;
|
---|
190 | WORD Digit;
|
---|
191 | WORD Power=0xF000;
|
---|
192 | WORD ShiftVal=12;
|
---|
193 |
|
---|
194 | while (Power)
|
---|
195 | {
|
---|
196 | Digit=(wHexVal & Power)>>ShiftVal;
|
---|
197 | if (Digit)
|
---|
198 | fNonZero=TRUE;
|
---|
199 |
|
---|
200 | if (Digit ||
|
---|
201 | fNonZero ||
|
---|
202 | (Option & LEADING_ZEROES) ||
|
---|
203 | ((Power==0x0F) && (fNonZero==FALSE)))
|
---|
204 | //*StrPtr++=(char)('0'+Digit);
|
---|
205 | *StrPtr++=ddhextab[Digit];
|
---|
206 |
|
---|
207 | Power>>=4;
|
---|
208 | ShiftVal-=4;
|
---|
209 | } // end while
|
---|
210 |
|
---|
211 | return (StrPtr);
|
---|
212 | }
|
---|
213 |
|
---|
214 | //----------- ddprintf_HexLongToASCII -
|
---|
215 | PSZ LOG::_HexLongToASCII( PSZ StrPtr, DWORD wHexVal, WORD Option )
|
---|
216 | {
|
---|
217 | BOOL fNonZero=FALSE;
|
---|
218 | DWORD Digit;
|
---|
219 | DWORD Power=0xF0000000;
|
---|
220 | DWORD ShiftVal=28;
|
---|
221 |
|
---|
222 | while (Power)
|
---|
223 | {
|
---|
224 | Digit=(wHexVal & Power)>>ShiftVal;
|
---|
225 | if (Digit)
|
---|
226 | fNonZero=TRUE;
|
---|
227 |
|
---|
228 | if (Digit ||
|
---|
229 | fNonZero ||
|
---|
230 | (Option & LEADING_ZEROES) ||
|
---|
231 | ((Power==0x0F) && (fNonZero==FALSE)))
|
---|
232 | *StrPtr++=ddhextab[Digit];
|
---|
233 |
|
---|
234 | if (Power==0xF0000000) // 1 billion
|
---|
235 | Power=0xF000000;
|
---|
236 | else if (Power==0xF000000)
|
---|
237 | Power=0xF00000;
|
---|
238 | else if (Power==0xF00000)
|
---|
239 | Power=0xF0000;
|
---|
240 | else if (Power==0xF0000)
|
---|
241 | Power=0xF000;
|
---|
242 | else if (Power==0xF000)
|
---|
243 | Power=0xF00;
|
---|
244 | else if (Power==0xF00)
|
---|
245 | Power=0xF0;
|
---|
246 | else if (Power==0xF0)
|
---|
247 | Power=0xF;
|
---|
248 | else Power=0;
|
---|
249 |
|
---|
250 | ShiftVal-=4;
|
---|
251 | } // end while
|
---|
252 |
|
---|
253 | return (StrPtr);
|
---|
254 | }
|
---|
255 |
|
---|
256 |
|
---|
257 | USHORT LOG::_ddsprintf ( PSZ pszOutString, PSZ pszFmtString, STACK_ADR Parm )
|
---|
258 | /*
|
---|
259 | ; ddsprintf - "sprintf" function on a vbl number of arguments.
|
---|
260 | ;
|
---|
261 | ; pszOutString - Output string saved here.
|
---|
262 | ; pszFmtString - Input, Ascii string containing text and formating information.
|
---|
263 | ; Parm - Input, Address of the 1st of the variable number of arguments.
|
---|
264 | ;
|
---|
265 | ;Returns:
|
---|
266 | ; Length of string created.
|
---|
267 | */
|
---|
268 | {
|
---|
269 | PSZ BuildPtr = pszOutString;
|
---|
270 | PSZ pStr = (PSZ) pszFmtString;
|
---|
271 | PSZ SubStr;
|
---|
272 | WORD wBuildOption;
|
---|
273 |
|
---|
274 | while (*pStr) {
|
---|
275 | // don't overflow target
|
---|
276 | if (BuildPtr >= &pszOutString[ MAX_MsgLen-2 ] )
|
---|
277 | break;
|
---|
278 |
|
---|
279 | switch (*pStr) { // the top switch
|
---|
280 | case '%':
|
---|
281 | wBuildOption=0;
|
---|
282 | pStr++;
|
---|
283 | if (*pStr=='0') {
|
---|
284 | wBuildOption|=LEADING_ZEROES;
|
---|
285 | pStr++;
|
---|
286 | }
|
---|
287 |
|
---|
288 | switch(*pStr) { // switch on "%" options
|
---|
289 | case 'x':
|
---|
290 | case 'X':
|
---|
291 | BuildPtr=_HexWordToASCII(BuildPtr, *Parm.WordPtr++,wBuildOption);
|
---|
292 | pStr++;
|
---|
293 | continue;
|
---|
294 |
|
---|
295 | case 'd':
|
---|
296 | case 'D':
|
---|
297 | BuildPtr=_DecWordToASCII(BuildPtr, *Parm.WordPtr++,wBuildOption);
|
---|
298 | pStr++;
|
---|
299 | continue;
|
---|
300 |
|
---|
301 | case 's':
|
---|
302 | case 'S':
|
---|
303 | SubStr = (PSZ) *Parm.StringPtr;
|
---|
304 | while (*SubStr)
|
---|
305 | *BuildPtr++ = *SubStr++;
|
---|
306 | Parm.StringPtr++;
|
---|
307 | BuildPtr--; // remove the \0
|
---|
308 | pStr++;
|
---|
309 | continue;
|
---|
310 |
|
---|
311 | case 'l':
|
---|
312 | case 'L':
|
---|
313 | pStr++;
|
---|
314 | switch (*pStr) { // "%l" options
|
---|
315 | case 'x':
|
---|
316 | BuildPtr=_HexLongToASCII(BuildPtr, *Parm.LongPtr++,wBuildOption);
|
---|
317 | pStr++;
|
---|
318 | continue;
|
---|
319 |
|
---|
320 | case 'd':
|
---|
321 | BuildPtr=_DecLongToASCII(BuildPtr, *Parm.LongPtr++,wBuildOption);
|
---|
322 | pStr++;
|
---|
323 | continue;
|
---|
324 | } // end switch on "%l" options
|
---|
325 | continue; // dunno what he wants
|
---|
326 |
|
---|
327 | case 0:
|
---|
328 | continue;
|
---|
329 | } // end switch on "%" options
|
---|
330 | break;
|
---|
331 |
|
---|
332 | case '\\':
|
---|
333 | pStr++;
|
---|
334 | switch (*pStr) {
|
---|
335 | case 'n':
|
---|
336 | *BuildPtr++=CR;
|
---|
337 | *BuildPtr++=LF;
|
---|
338 | pStr++;
|
---|
339 | continue;
|
---|
340 |
|
---|
341 | case 'r':
|
---|
342 | *BuildPtr++=CR;
|
---|
343 | pStr++;
|
---|
344 | continue;
|
---|
345 |
|
---|
346 | case 0:
|
---|
347 | continue;
|
---|
348 |
|
---|
349 | } // end switch
|
---|
350 |
|
---|
351 | break; // case '\\'
|
---|
352 |
|
---|
353 | case '\n':
|
---|
354 | pStr++;
|
---|
355 | *BuildPtr++=CR;
|
---|
356 | *BuildPtr++=LF;
|
---|
357 | continue;
|
---|
358 | break;
|
---|
359 | } // end top switch
|
---|
360 |
|
---|
361 | *BuildPtr++=*pStr++;
|
---|
362 | } // end while
|
---|
363 |
|
---|
364 | *BuildPtr=0; // cauterize the string
|
---|
365 | return strlen( (char *) pszOutString );
|
---|
366 | }
|
---|
367 |
|
---|
368 | USHORT _CheckRing(void);
|
---|
369 | #pragma aux _CheckRing = \
|
---|
370 | "push cs" \
|
---|
371 | "pop ax " \
|
---|
372 | "and ax,0003H" \
|
---|
373 | parm nomemory \
|
---|
374 | modify [ax];
|
---|
375 |
|
---|
376 | //----------------------- ddputstring -
|
---|
377 | void LOG::_ddputstring ( USHORT iMsgNum, PSZ pszMsg )
|
---|
378 | {
|
---|
379 | int iMsgLength = strlen( (char *) pszMsg );
|
---|
380 | // Sring length of the message.
|
---|
381 |
|
---|
382 | // Need to know whether we're still executing at Ring 3.
|
---|
383 | if ( _bInRing3 )
|
---|
384 | if (_CheckRing() != 3) // In Ring 3 last time, still there now?
|
---|
385 | _bInRing3 = FALSE; // Nope, and no need to check again.
|
---|
386 |
|
---|
387 | // --- Index through possible places to save this message.
|
---|
388 | for (int destination=0; destination != _nMsgSinks; ++destination) {
|
---|
389 | if ( bMsgSink[destination] ) {
|
---|
390 | switch (destination) {
|
---|
391 | case _Display:
|
---|
392 | // Put message on the display only if we're in Ring 3.
|
---|
393 | if ( _bInRing3 ) {
|
---|
394 | static CHAR szCRLF[] = "\r\n";
|
---|
395 | static int iCRLF_Len = strlen( (char *) szCRLF );
|
---|
396 | DosPutMessage( 1, iMsgLength, (PCHAR) pszMsg );
|
---|
397 | DosPutMessage( 1, iCRLF_Len, (PCHAR) szCRLF );
|
---|
398 | }
|
---|
399 | break;
|
---|
400 | case _SerialLine:
|
---|
401 | { PCHAR pChar = (PCHAR) pszMsg;
|
---|
402 | while (*pChar)
|
---|
403 | _CharOut(*pChar++);
|
---|
404 | }
|
---|
405 | _CharOut( '\n' );
|
---|
406 | break;
|
---|
407 | case _ErrorLog:
|
---|
408 | if ( _bInRing3 )
|
---|
409 | DosSysTrace( _DosTraceMajorCode, iMsgLength, iMsgNum, (PCHAR) pszMsg);
|
---|
410 | else
|
---|
411 | DevHelp_RAS( _DosTraceMajorCode, iMsgNum, iMsgLength, pszMsg);
|
---|
412 | break;
|
---|
413 | case _TraceLog:
|
---|
414 | if ( _bInRing3 )
|
---|
415 | DosSysTrace( _DosTraceMajorCode, iMsgLength, iMsgNum, (PCHAR) pszMsg);
|
---|
416 | else
|
---|
417 | DevHelp_RAS( _DosTraceMajorCode, iMsgNum, iMsgLength, pszMsg);
|
---|
418 | break;
|
---|
419 | }
|
---|
420 | }
|
---|
421 | }
|
---|
422 | }
|
---|
423 |
|
---|
424 |
|
---|
425 | void LOG::_CharOut(char c)
|
---|
426 | /* Sends a single character to the COM: port. */
|
---|
427 | {
|
---|
428 | UCHAR inbyte;
|
---|
429 |
|
---|
430 | inbyte = inp((_ComPort + UART_LINE_STAT));
|
---|
431 | while ((inbyte & 0x20) != 0x20) {
|
---|
432 | iodelay(1);
|
---|
433 | inbyte = inp((_ComPort + UART_LINE_STAT));
|
---|
434 | }
|
---|
435 | // Send the character
|
---|
436 | outp((_ComPort + UART_DATA), c);
|
---|
437 | }
|
---|
438 |
|
---|
439 |
|
---|
440 | // Create a log. The parms indicate where to stream the messages to.
|
---|
441 | LOG::LOG( USHORT DosTraceMajorCode, PSZ* apszMsgText ) :
|
---|
442 | _DosTraceMajorCode ( DosTraceMajorCode ),
|
---|
443 | _bInRing3 ( _CheckRing() != 0 ),
|
---|
444 | _apszMsgText ( apszMsgText ),
|
---|
445 | _ComPort ( 0x2F8 )
|
---|
446 | {
|
---|
447 | bMsgSink[ _Display ] = FALSE;
|
---|
448 | bMsgSink[ _SerialLine ] = FALSE;
|
---|
449 | bMsgSink[ _ErrorLog ] = FALSE;
|
---|
450 | bMsgSink[ _TraceLog ] = TRUE;
|
---|
451 | }
|
---|
452 |
|
---|
453 |
|
---|
454 | virtual void LOG::vTrace( USHORT eventNum )
|
---|
455 | /* Log the specified event. */
|
---|
456 | {
|
---|
457 | //--- Output the string.
|
---|
458 | _ddputstring( eventNum, _apszMsgText[ eventNum ] );
|
---|
459 | }
|
---|
460 |
|
---|
461 |
|
---|
462 | virtual void LOG::vLog( USHORT eventNum, ... )
|
---|
463 | /* Log the specified event, with data. */
|
---|
464 | {
|
---|
465 | STACK_ADR Arg1Adr; // Points to the 1st of a variable number
|
---|
466 | // of arguments in the stack.
|
---|
467 | PUSHORT pEventNum;
|
---|
468 |
|
---|
469 | //--- Get the stack address of the 1st argument following the error number.
|
---|
470 | pEventNum = (PUSHORT) &eventNum; // Adr of event num
|
---|
471 | ++pEventNum; // Advance ptr past 1st arg.
|
---|
472 | Arg1Adr.VoidPtr = (PVOID) pEventNum; // Adr of 1st after err num.
|
---|
473 |
|
---|
474 | //--- Format the message and any of the data.
|
---|
475 | //### Should have check here for error number out of range.
|
---|
476 | _ddsprintf( _dd_BuildString, _apszMsgText[ eventNum ], Arg1Adr );
|
---|
477 |
|
---|
478 | //--- Output the string.
|
---|
479 | _ddputstring( eventNum, _dd_BuildString );
|
---|
480 | }
|
---|
481 |
|
---|
482 |
|
---|
483 | PERFLOG::PERFLOG( USHORT DosTraceMajorCode, PSZ* apszMsgText ) :
|
---|
484 | LOG( DosTraceMajorCode, apszMsgText )
|
---|
485 | {
|
---|
486 | bMsgSink[ _Display ] = FALSE;
|
---|
487 | bMsgSink[ _SerialLine ] = FALSE;
|
---|
488 | bMsgSink[ _ErrorLog ] = FALSE;
|
---|
489 | bMsgSink[ _TraceLog ] = TRUE;
|
---|
490 | }
|
---|
491 |
|
---|
492 | virtual void PERFLOG::vTrace( USHORT eventNum )
|
---|
493 | {
|
---|
494 | RDTSC_COUNT rdtsc_result; // Output from Pentium timing instruction.
|
---|
495 | rdtsc( &rdtsc_result );
|
---|
496 | if ( _CheckRing() )
|
---|
497 | DosSysTrace( _DosTraceMajorCode, sizeof(RDTSC_COUNT), eventNum, (PCHAR) &rdtsc_result);
|
---|
498 | else
|
---|
499 | DevHelp_RAS( _DosTraceMajorCode, eventNum, sizeof(RDTSC_COUNT), (PSZ) &rdtsc_result);
|
---|
500 | }
|
---|
501 |
|
---|
502 |
|
---|
503 | USHORT BINARYLOG::_ddsprintf ( PSZ pszOutString, PSZ pszFmtString, STACK_ADR Parm )
|
---|
504 | /*
|
---|
505 | ; ddsprintf - "sprintf" function on a vbl number of arguments.
|
---|
506 | ;
|
---|
507 | ; pszOutString - Output string saved here.
|
---|
508 | ; pszFmtString - Input, Ascii string containing text and formating information.
|
---|
509 | ; Parm - Input, Address of the 1st of the variable number of arguments.
|
---|
510 | ;
|
---|
511 | ;Returns
|
---|
512 | ; USHORT nDataLen - lentgh of the data string that is saved in pszOutString
|
---|
513 | ;
|
---|
514 | ;Notes
|
---|
515 | ; This function needed to reverse the order of the args pushed on the stack.
|
---|
516 | */
|
---|
517 | {
|
---|
518 | PSZ pStr = (PSZ) pszFmtString;
|
---|
519 | USHORT uStrLen = 0; // Total string length accumulated here.
|
---|
520 | USHORT nBytes; // Length of one data item saved here.
|
---|
521 | BOOL lFlag;
|
---|
522 |
|
---|
523 | /*--- Find out how many bytes of log data have been pushed on
|
---|
524 | * the stack. Do this by walking formatting string and counting
|
---|
525 | * the number of bytes expected by the format control characters.
|
---|
526 | */
|
---|
527 | while ( *pStr ) {
|
---|
528 |
|
---|
529 | /* ### FUTURE: Want to seek forward to '%' or '0'. Any quick way to do it? */
|
---|
530 |
|
---|
531 | if (*pStr != '%') { // If not the start of a format directive,
|
---|
532 | ++pStr; // then continue to next byte.
|
---|
533 | continue;
|
---|
534 | }
|
---|
535 |
|
---|
536 | nBytes = 0; // Not 0 indicates a recognized sequence.
|
---|
537 | lFlag = FALSE; // Set TRUE when "L" is present.
|
---|
538 | ++ pStr; // Advance past '%'
|
---|
539 | if (*pStr == '0') // Advance past '0'
|
---|
540 | ++pStr;
|
---|
541 | if (*pStr == 'l' || *pStr == 'L') {
|
---|
542 | ++pStr; // Advance past "L" if present.
|
---|
543 | lFlag = TRUE;
|
---|
544 | }
|
---|
545 |
|
---|
546 | if (*pStr == 'b' || *pStr == 'B')
|
---|
547 | nBytes = 1;
|
---|
548 | else if (*pStr == 'd' || *pStr == 'D' || *pStr == 'x' || *pStr == 'X') {
|
---|
549 | if (lFlag)
|
---|
550 | nBytes = 4;
|
---|
551 | else
|
---|
552 | nBytes = 2;
|
---|
553 | }
|
---|
554 | else if (*pStr == 'q' || *pStr == 'Q')
|
---|
555 | nBytes = 8;
|
---|
556 |
|
---|
557 | /* If we recognize the formatting command, then count the bytes,
|
---|
558 | * otherwise ignore this '%' directive and continue.
|
---|
559 | */
|
---|
560 | if (nBytes) {
|
---|
561 | _fmemcpy( (PVOID) pszOutString, Parm.VoidPtr, nBytes );
|
---|
562 | //Rudi: stack is word-wise !
|
---|
563 | if( nBytes == 1 )
|
---|
564 | Parm.BytePtr += 2;
|
---|
565 | else
|
---|
566 | Parm.BytePtr += nBytes;
|
---|
567 |
|
---|
568 | pszOutString += nBytes;
|
---|
569 | uStrLen += nBytes;
|
---|
570 | }
|
---|
571 |
|
---|
572 | ++pStr;
|
---|
573 | }
|
---|
574 | return( uStrLen );
|
---|
575 | }
|
---|
576 |
|
---|
577 |
|
---|
578 | BINARYLOG::BINARYLOG( USHORT DosTraceMajorCode, PSZ* apszMsgText ) :
|
---|
579 | LOG( DosTraceMajorCode, apszMsgText )
|
---|
580 | {
|
---|
581 | bMsgSink[ _Display ] = FALSE;
|
---|
582 | bMsgSink[ _SerialLine ] = FALSE;
|
---|
583 | bMsgSink[ _ErrorLog ] = FALSE;
|
---|
584 | bMsgSink[ _TraceLog ] = TRUE;
|
---|
585 | }
|
---|
586 |
|
---|
587 |
|
---|
588 | virtual void BINARYLOG::vTrace( USHORT eventNum )
|
---|
589 | /* Log the specified trace point. */
|
---|
590 | {
|
---|
591 | //--- Save the event in the system trace log.
|
---|
592 | if ( _CheckRing() )
|
---|
593 | DosSysTrace( _DosTraceMajorCode, 0, eventNum, (PCHAR) NULL );
|
---|
594 | else
|
---|
595 | DevHelp_RAS( _DosTraceMajorCode, eventNum, 0, (PSZ) NULL );
|
---|
596 | }
|
---|
597 |
|
---|
598 |
|
---|
599 | void BINARYLOG::vLog( USHORT eventNum, ... )
|
---|
600 | /* Log the specified trace point, with data. */
|
---|
601 | {
|
---|
602 | STACK_ADR pStack; // Points to the 1st of a variable number
|
---|
603 | // of arguments in the stack.
|
---|
604 | USHORT usLength; // Number of bytes to log.
|
---|
605 |
|
---|
606 | //--- Get the stack address of the 1st argument following the event number.
|
---|
607 | pStack.WordPtr = (WORD*) &eventNum; // Adr of event num
|
---|
608 | ++pStack.WordPtr; // Advance ptr to 1st arg after event number.
|
---|
609 |
|
---|
610 | //--- Invoke binary version of _ddsprintf() to get args into the right order.
|
---|
611 | usLength = _ddsprintf( _dd_BuildString, _apszMsgText[ eventNum ], pStack );
|
---|
612 |
|
---|
613 | //--- Save data bytes in the System trace log and return.
|
---|
614 | if ( _CheckRing() )
|
---|
615 | DosSysTrace( _DosTraceMajorCode, usLength, eventNum, (PCHAR) _dd_BuildString );
|
---|
616 | else
|
---|
617 | DevHelp_RAS( _DosTraceMajorCode, eventNum, usLength, (PSZ) _dd_BuildString );
|
---|
618 | }
|
---|