source: trunk/src/kernel32/dbglog.cpp@ 21957

Last change on this file since 21957 was 21957, checked in by dmik, 14 years ago

Print human readable time stamp in log files.

Also clean up the code and format so that the prefix
has permanent alignment and takes less space.

File size: 31.3 KB
Line 
1/* $Id: dbglog.cpp,v 1.9 2003-03-26 16:02:33 sandervl Exp $ */
2
3/*
4 * Project Odin Software License can be found in LICENSE.TXT
5 * Debug Logging procedures
6 *
7 * Copyright 1998-2002 Sander van Leeuwen (sandervl@xs4all.nl)
8 * Copyright 1998 Joel Troster
9 * Copyright 1998 Peter FitzSimmons
10 *
11 */
12
13
14/*******************************************************************************
15* Internal Functions *
16*******************************************************************************/
17
18#define INCL_MISC
19#define INCL_BASE
20#define INCL_WIN
21#define INCL_WINERRORS
22#define INCL_DOSFILEMGR
23#include <os2wrap.h> //Odin32 OS/2 api wrappers
24#include <stdio.h>
25#include <stdlib.h>
26#include <string.h>
27#include <stdarg.h>
28#include <process.h>
29#include <win32type.h>
30#include <win32api.h>
31#include <dbglog.h>
32#include "initterm.h"
33#include "logging.h"
34#include "exceptions.h"
35#include "exceptutil.h"
36#include <wprocess.h>
37#include <versionos2.h>
38#include "odinbuild.h"
39#include <cpuhlp.h>
40
41#include "asmutil.h"
42#include "WinImageBase.h"
43#include "WinDllBase.h"
44#include "WinExeBase.h"
45/*****************************************************************************
46 * PMPRINTF Version *
47 *****************************************************************************/
48
49#ifdef PMPRINTF
50
51/* ----- Customization variables ----- */
52#define PRINTFID ""
53#define PRINTFMAXLEN 300
54#define PRINTFLINELEN 100
55#define PRINTFTHREADS 54
56#define PRINTFQNAME "\\QUEUES\\PRINTF32"
57
58/* ----- Includes and externals ----- */
59#include <stddef.h> /* .. */
60#include <time.h> /* .. */
61
62extern ULONG flAllocMem; /*Tue 03.03.1998: knut */
63
64/* ----- Local defines ----- */
65#define PRINTFIDSIZE sizeof(PRINTFID)
66#define PRINTFMAXBUF PRINTFIDSIZE+PRINTFLINELEN
67
68ULONG GetPentiumTSC (QWORD * tsc);
69
70/*****************************************************************************
71 * Structures *
72 *****************************************************************************/
73
74/* ----- Per-thread output buffer and current indices into line ---- */
75struct perthread {
76 LONG lineindex; /* where next char */
77 LONG tidemark; /* rightmost char */
78 int bell; /* TRUE if line has bell */
79 UCHAR line[PRINTFMAXBUF]; /* accumulator */
80 };
81
82/* ----- Local static variables ----- */
83static ULONG ourpid=0; /* our process ID */
84static ULONG servepid=0; /* process IDs of the server */
85static HQUEUE qhandle=0; /* handle for the queue */
86static struct perthread *tps[PRINTFTHREADS+1]; /* -> per-thread data */
87
88/* ----- Local subroutine ----- */
89static int printf_(struct perthread *);
90
91
92/* ----------------------------------------------------------------- */
93/* The "printf" function. Note this has a variable number of */
94/* arguments. */
95/* ----------------------------------------------------------------- */
96int SYSTEM WriteLog(const char *f, ...)
97 {
98 TIB *ptib; /* process/thread id structures */
99 PIB *ppib; /* .. */
100 TID ourtid; /* thread ID */
101 struct perthread *tp; /* pointer to per-thread data */
102 int rc; /* returncode */
103 ULONG urc; /* returncode */
104
105 urc=DosOpenQueue(&servepid, &qhandle, PRINTFQNAME); /* Open the Q */
106 /* Non-0 RC means Q does not exist or cannot be opened */
107 if (urc==343) return 0; /* queue does not exist, so quit */
108 if (urc!=0) return -1; /* report any other error */
109
110 /* First determine our thread ID (and hence get access to the */
111 /* correct per-thread data. If the per-thread data has not been */
112 /* allocated, then allocate it now. It is never freed, once */
113 /* allocated, as PRINTF is not notified of end-of-thread. */
114 DosGetInfoBlocks(&ptib,&ppib); /* get process/thread info */
115 ourtid=ptib->tib_ptib2->tib2_ultid; /* .. and copy TID */
116 if (ourtid>PRINTFTHREADS) /* too many threads .. */
117 return 0; /* .. so quit, quietly */
118 tp=tps[ourtid]; /* copy to local pointer */
119 if (tp==NULL) { /* uninitialized (NULL=0) */
120 /* allocate a per-thread structure */
121 tp=(struct perthread *)malloc(sizeof(struct perthread));
122 if (tp==NULL) return -1; /* out of memory -- return error */
123 tps[ourtid]=tp; /* save for future calls */
124 strcpy(tp->line,PRINTFID); /* initialize: line.. */
125 tp->lineindex=PRINTFIDSIZE-1; /* ..where next char */
126 tp->tidemark =PRINTFIDSIZE-2; /* ..rightmost char */
127 tp->bell=FALSE; /* ..if line has bell */
128 if (ourpid==0) ourpid=ppib->pib_ulpid; /* save PID for all to use */
129 }
130
131 { /* Block for declarations -- only needed if queue exists, etc. */
132 LONG count; /* count of characters formatted */
133 UCHAR buffer[PRINTFMAXLEN+1]; /* formatting area */
134 LONG i, newind; /* work */
135 UCHAR ch; /* .. */
136 va_list argptr; /* -> variable argument list */
137
138 va_start(argptr, f); /* get pointer to argument list */
139 count=vsprintf(buffer, f, argptr);
140 va_end(argptr); /* done with variable arguments */
141
142 if (count<0) return count-1000;/* bad start */
143
144 if (count>PRINTFMAXLEN) {
145 /* Disaster -- we are probably "dead", but just in case we */
146 /* are not, carry on with truncated data. */
147 count=PRINTFMAXLEN;
148 }
149 buffer[count]='\0'; /* ensure terminated */
150 /* OK, ready to go with the data now in BUFFER */
151 /* We copy from the formatted string to the output (line) buffer, */
152 /* taking note of certain control characters and sending a line */
153 /* the queue whenever we see a LF control, or when the line */
154 /* fills (causing a forced break). */
155 for (i=0; ; i++) {
156 ch=buffer[i]; if (!ch) break;
157 switch(ch) {
158 case '\r': /* carriage return */
159 tp->lineindex=PRINTFIDSIZE-1; /* back to start of line */
160 break;
161 case '\n': /* new line */
162 case '\f': /* form feed */
163 rc=printf_(tp); /* print a line */
164 if (rc!=0) return rc; /* error */
165 break;
166 case '\t': /* tab */
167 newind=tp->lineindex-PRINTFIDSIZE+1; /* offset into data */
168 newind=tp->lineindex+5-newind%5; /* new index requested */
169 if (newind>=PRINTFMAXBUF) newind=PRINTFMAXBUF; /* clamp */
170 for (; tp->lineindex<newind; tp->lineindex++) {
171 if (tp->lineindex>tp->tidemark) { /* beyond current end */
172 tp->line[tp->lineindex]=' '; /* add space */
173 tp->tidemark=tp->lineindex;
174 }
175 }
176 break;
177 case '\v': /* vertical tab */
178 /* ignore it */
179 break;
180 case '\b': /* backspace */
181 tp->lineindex=max(tp->lineindex-1,PRINTFIDSIZE);
182 break;
183 case '\a': /* alert (bell) */
184 tp->bell=TRUE;
185 break;
186 default: /* ordinary character */
187 tp->line[tp->lineindex]=ch;
188 if (tp->lineindex>tp->tidemark) /* is rightmost.. */
189 tp->tidemark=tp->lineindex;
190 tp->lineindex++; /* step for next */
191 } /* switch */
192 if (tp->lineindex>=PRINTFMAXBUF) {
193 rc=printf_(tp); /* print a line */
194 if (rc!=0) return rc; /* error */
195 }
196
197 } /* copy loop */
198 return count; /* all formatted data processed */
199 } /* block */
200 } /* printf */
201
202/* ----- printf_(tp) -- Local subroutine to send a line ------------ */
203/* A line has been completed (or overflowed): write it to the queue. */
204int printf_(struct perthread *tp) /* pointer to per-thread data */
205 {
206 ULONG urc; /* unsigned returncode */
207 PSZ pszTo, pszFrom; /* character pointers */
208 PVOID addr; /* address of output data */
209 long size; /* total size of output data */
210 time_t timenow; /* holds current time */
211
212 tp->line[tp->tidemark+1]='\0'; /* add terminator */
213 size=tp->tidemark+2; /* total length of data */
214
215 /* Get some shared memory that can be given away */
216 urc=DosAllocSharedMem(&addr, NULL, (unsigned)size,
217 OBJ_GIVEABLE|PAG_WRITE|PAG_COMMIT|flAllocMem);
218 /*knut: added flAllocMem */
219
220 if (urc!=0) return -2; /* error */
221
222 pszTo=addr; /* copy for clarity */
223 pszFrom=&(tp->line[0]); /* pointer to source */
224 strcpy(pszTo,pszFrom); /* copy the string to shared memory */
225
226 if (ourpid!=servepid) { /* (no giveaway needed if to self) */
227 urc=DosGiveSharedMem(addr, servepid, PAG_READ); /* give access */
228 if (urc!=0) return -3;} /* error */
229
230 /* Write the selector, size, and timestamp to the queue */
231 if (tp->bell) size=-size; /* BELL passed by negation */
232 time(&timenow); /* optional - else use 0 */
233 urc=DosWriteQueue(qhandle, /* handle */
234 (unsigned)timenow, /* 'request' (timestamp) */
235 (unsigned)size, /* 'length' (length/bell) */
236 addr, /* 'address' (address) */
237 0); /* priority (FIFO if enabled) */
238 if (urc!=0) return -4; /* error */
239 if (ourpid!=servepid) { /* if given away.. */
240 urc=DosFreeMem(addr); /* .. *we* are done with it */
241 if (urc!=0) return -5;} /* error */
242 /* Reset the line buffer and indices */
243 tp->lineindex=PRINTFIDSIZE-1; /* where next char */
244 tp->tidemark =PRINTFIDSIZE-2; /* rightmost char */
245 tp->bell =FALSE; /* true if line has bell */
246 return 0; /* success! */
247 } /* printf_ */
248#endif
249
250
251
252/*****************************************************************************
253 * Standard Version *
254 *****************************************************************************/
255
256static FILE *flog = NULL; /*PLF Mon 97-09-08 20:00:15*/
257static BOOL init = FALSE;
258static BOOL firstTime = FALSE;
259static BOOL fLogging = TRUE;
260static int dwEnableLogging = 1;
261#ifdef __IBMC__
262static int oldcrtmsghandle = 0;
263#endif
264
265static BOOL fDisableThread[5] = {0};
266static BOOL fFlushLines = TRUE;
267
268static const char *pszLastLogEntry = NULL;
269
270//#define CHECK_ODINHEAP
271#if defined(DEBUG) && defined(CHECK_ODINHEAP)
272int checkOdinHeap = 1;
273int checkingheap = 0;
274#define ODIN_HEAPCHECK() \
275 if(checkingheap) checkOdinHeap = 0; \
276 checkingheap++; \
277 if(checkOdinHeap) _heap_check(); \
278 checkingheap--;
279#else
280#define ODIN_HEAPCHECK()
281#endif
282
283#define LOG_TIME
284//#define SHOW_FPU_CONTROLREG
285#define WIN32_IP_LOGGING
286#define WIN32_IP_LOG_PORT 5001
287
288#ifdef WIN32_IP_LOGGING
289#include <types.h>
290#include <netinet/in.h>
291#include <sys/socket.h>
292
293static int logSocket = -1;
294static struct sockaddr_in servername;
295#endif
296
297#ifdef LOG_TIME
298static DWORD startTicks = 0;
299static DWORD startTime = 0;
300VOID WINAPI GetLocalTime(LPSYSTEMTIME);
301#endif
302
303static void win32modname (ULONG eip, char *szModName, int cbModName)
304{
305 Win32ImageBase *pMod = NULL;
306 if (WinExe && WinExe->insideModule(eip))
307 pMod = WinExe;
308 else
309 pMod = Win32DllBase::findModuleByAddr(eip);
310 if (pMod != NULL)
311 {
312 szModName[0] = '\0';
313 strncat(szModName, pMod->getModuleName(), cbModName);
314 }
315}
316
317int SYSTEM WriteLog(const char *tekst, ...)
318{
319 USHORT sel = RestoreOS2FS();
320 va_list argptr;
321 TEB *teb = GetThreadTEB();
322
323 pszLastLogEntry = tekst;
324
325 ODIN_HEAPCHECK();
326
327 if (!init)
328 {
329 init = TRUE;
330 firstTime = TRUE;
331
332#ifdef LOG_TIME
333 // initialize the current time counter
334 startTicks = GetTickCount();
335 SYSTEMTIME t;
336 GetLocalTime(&t);
337 startTime = t.wHour * 3600 + t.wMinute * 60 + t.wSecond;
338 startTime = (startTime * 1000) + t.wMilliseconds;
339#endif
340
341 if(getenv("WIN32LOG_FLUSHLINES"))
342 fFlushLines = TRUE;
343
344#ifdef DEFAULT_LOGGING_OFF
345 if(getenv("WIN32LOG_ENABLED"))
346 {
347#else
348 if(!getenv("NOWIN32LOG"))
349 {
350#endif
351#ifdef WIN32_IP_LOGGING
352 char *logserver = getenv("WIN32LOG_IPSERVER");
353 if(logserver) {
354 sock_init();
355
356 memset(&servername, 0, sizeof(servername));
357 servername.sin_family = AF_INET;
358 servername.sin_addr.s_addr = inet_addr(logserver);
359 servername.sin_port = WIN32_IP_LOG_PORT;
360
361 logSocket = socket(PF_INET, SOCK_DGRAM, 0);
362 }
363#endif
364 char szLogFile[CCHMAXPATH];
365 const char *pszLogBase = getenv("WIN32LOG_FILEBASE");
366 if (!pszLogBase)
367 pszLogBase = "odin32_";
368
369 sprintf(szLogFile, "%s%d.log", pszLogBase, getpid());
370 flog = fopen(szLogFile, "w");
371 if(flog == NULL)
372 {//probably running exe on readonly device
373 sprintf(szLogFile, "%sodin32_%d.log", kernel32Path, getpid());
374 flog = fopen(szLogFile, "w");
375 }
376#ifdef __IBMC__
377 oldcrtmsghandle = _set_crt_msg_handle(fileno(flog));
378#endif
379 }
380 else
381 fLogging = FALSE;
382
383 fDisableThread[0] = getenv("DISABLE_THREAD1") != NULL;
384 fDisableThread[1] = getenv("DISABLE_THREAD2") != NULL;
385 fDisableThread[2] = getenv("DISABLE_THREAD3") != NULL;
386 fDisableThread[3] = getenv("DISABLE_THREAD4") != NULL;
387 fDisableThread[4] = getenv("DISABLE_THREAD5") != NULL;
388 }
389
390 if (teb)
391 {
392 if(teb->o.odin.threadId < 5 && fDisableThread[teb->o.odin.threadId-1] == 1)
393 {
394 SetFS(sel);
395 return 1;
396 }
397 }
398
399 if (!tekst)
400 {
401 if (flog)
402 fflush( flog);
403 SetFS(sel);
404 return 1;
405 }
406
407#ifdef LOG_TIME
408 // get human readable time values
409 DWORD time = startTime + (GetTickCount() - startTicks);
410 DWORD h = time / 3600000;
411 DWORD m = (time %= 3600000) / 60000;
412 DWORD s = (time %= 60000) / 1000;
413 DWORD ms = time % 1000;
414#endif
415
416 if (fLogging && flog && (dwEnableLogging > 0))
417 {
418 if (firstTime)
419 {
420 firstTime = FALSE;
421
422 // print the header with the legend
423#ifdef LOG_TIME
424 fprintf(flog,
425 " /--------------------- Thread ID\n"
426 " | /----------------- Call Depth\n"
427 " | | /-------------- Flags (O = OS/2 mode (FS=150B))\n"
428 " | | | /------- Current Time\n"
429 "--- --- - ------------\n");
430#else
431#ifdef SHOW_FPU_CONTROLREG
432 fprintf(flog,
433 " /------------ Thread ID\n"
434 " | /-------- Call Depth\n"
435 " | | /----- Flags (O = OS/2 mode (FS=150B))\n"
436 " | | | /-- FPU Control Register\n"
437 "--- --- - ---\n");
438#else
439 fprintf(flog,
440 " /-------- Thread ID\n"
441 " | /---- Call Depth\n"
442 " | | /- Flags (O = OS/2 mode (FS=150B))\n"
443 "--- --- -\n");
444#endif
445#endif
446 }
447
448 va_start(argptr, tekst);
449
450#ifdef WIN32_IP_LOGGING
451 if (logSocket == -1)
452 {
453#endif
454 if (teb)
455 {
456 ULONG ulCallDepth;
457#ifdef DEBUG
458 ulCallDepth = teb->o.odin.dbgCallDepth;
459#else
460 ulCallDepth = 0;
461#endif
462
463 teb->o.odin.logfile = (DWORD)flog;
464
465#ifdef LOG_TIME
466 fprintf(flog,
467 "t%02d %03d %c %02d:%02d:%02d.%03d: ",
468 LOWORD(teb->o.odin.threadId),
469 ulCallDepth,
470 (sel == 0x150b && fSwitchTIBSel) ? 'O' : '-',
471 h, m, s, ms);
472#else
473#ifdef SHOW_FPU_CONTROLREG
474 fprintf(flog,
475 "t%02d %03d %c %03X: ",
476 LOWORD(teb->o.odin.threadId),
477 ulCallDepth,
478 (sel == 0x150b && fSwitchTIBSel) ? 'O' : '-',
479 CONTROL87(0,0));
480#else
481 fprintf(flog,
482 "t%02d %03d %c: ",
483 LOWORD(teb->o.odin.threadId),
484 ulCallDepth,
485 (sel == 0x150b && fSwitchTIBSel) ? 'O' : '-');
486#endif
487#endif
488 }
489 else
490 {
491#ifdef LOG_TIME
492 fprintf(flog,
493 "tXX ??? ? %02d:%02d:%02d.%03d: ",
494 h, m, s, ms);
495#else
496#ifdef SHOW_FPU_CONTROLREG
497 fprintf(flog,
498 "tXX ??? ? ???: ");
499#else
500 fprintf(flog,
501 "tXX ??? ?: ");
502#endif
503#endif
504 }
505#ifdef WIN32_IP_LOGGING
506 }
507#endif
508
509#ifdef WIN32_IP_LOGGING
510 if(logSocket != -1)
511 {
512 char logbuffer[1024];
513 int prefixlen = 0;
514
515 if (teb)
516 {
517 ULONG ulCallDepth;
518#ifdef DEBUG
519 ulCallDepth = teb->o.odin.dbgCallDepth;
520#else
521 ulCallDepth = 0;
522#endif
523#ifdef LOG_TIME
524 sprintf(logbuffer,
525 "t%02d %03d %02d:%02d:%02d.%03d [%c]: ",
526 LOWORD(teb->o.odin.threadId),
527 ulCallDepth,
528 h, m, s, ms,
529 (sel == 0x150b && fSwitchTIBSel) ? 'O' : '.');
530#else
531 sprintf(logbuffer,
532 "t%02d %03d [%c]: ",
533 LOWORD(teb->o.odin.threadId),
534 ulCallDepth,
535 (sel == 0x150b && fSwitchTIBSel) ? 'O' : '.');
536#endif
537 prefixlen = strlen(logbuffer);
538 }
539
540 vsprintf(&logbuffer[prefixlen], tekst, argptr);
541
542 int rc;
543
544 servername.sin_family = AF_INET;
545 servername.sin_port = WIN32_IP_LOG_PORT;
546
547 rc = sendto(logSocket, logbuffer, strlen(logbuffer)+1, 0, (struct sockaddr *)&servername, sizeof(servername));
548 if (rc == -1)
549 rc = sock_errno();
550 if (teb)
551 teb->o.odin.logfile = 0;
552 va_end(argptr);
553 }
554 else
555 {
556 vfprintf(flog, tekst, argptr);
557 if (teb)
558 teb->o.odin.logfile = 0;
559 va_end(argptr);
560
561 if (tekst[strlen(tekst)-1] != '\n')
562 fprintf(flog, "\n");
563#if 0
564 if (teb && LOWORD(teb->o.odin.threadId) > 1)
565 {
566 TEB *winteb = GetThreadTEB();
567 PWINEXCEPTION_FRAME pframe = (PWINEXCEPTION_FRAME)winteb->except;
568
569 fprintf(flog, "debug Win32 exception chain %08X (%08X) (teb = %08X, esp = %08X)\n", pframe, QueryExceptionChain(), teb, getESP());
570 fprintf(flog, "Top record at %08X, Prev at %08X, handler at %08X\n", (PWINEXCEPTION_FRAME)QueryExceptionChain(), ((PWINEXCEPTION_FRAME)QueryExceptionChain())->Prev, ((PWINEXCEPTION_FRAME)QueryExceptionChain())->Handler);
571 fprintf(flog, "*teb %08X %08X %08X %08X %08X %08X %08X %08X\n",
572 ((ULONG *)teb)[0],((ULONG *)teb)[1],((ULONG *)teb)[2],((ULONG *)teb)[3],
573 ((ULONG *)teb)[4],((ULONG *)teb)[5],((ULONG *)teb)[6],((ULONG *)teb)[7]);
574 while ((pframe != NULL) && ((ULONG)pframe != 0xFFFFFFFF)) {
575 if ((void *)pframe > winteb->stack_top || (void *)pframe < winteb->stack_low)
576 {
577 fprintf(flog, "Chain corrupted! Record at %08X is outside stack boundaries!\n", pframe);
578 break;
579 }
580
581 if ((ULONG)pframe < getESP())
582 {
583 fprintf(flog, "Chain corrupted! Record at %08X is below stack pointer!\n", pframe);
584 break;
585 }
586
587 char szModName[32] = "";
588 char szModName2[32] = "";
589 win32modname ((ULONG)pframe->Handler, szModName, sizeof (szModName));
590 win32modname ((ULONG)pframe->Prev, szModName2, sizeof (szModName2));
591 fprintf(flog, "Record at %08X, Prev at %08X [%s], handler at %08X [%s]\n", pframe, pframe->Prev, szModName2, pframe->Handler, szModName);
592 if (pframe == pframe->Prev) {
593 fprintf(flog, "Chain corrupted! Record at %08X pointing to itself!\n", pframe);
594 break;
595 }
596 pframe = pframe->Prev;
597 }
598 }
599#endif
600 if (fFlushLines)
601 fflush(flog);
602 }
603#else
604 vfprintf(flog, tekst, argptr);
605 if(teb) teb->o.odin.logfile = 0;
606 va_end(argptr);
607
608 if(tekst[strlen(tekst)-1] != '\n')
609 fprintf(flog, "\n");
610
611 if(fFlushLines)
612 fflush(flog);
613#endif
614 }
615
616 SetFS(sel);
617 return 1;
618}
619//******************************************************************************
620//******************************************************************************
621int SYSTEM WriteLogNoEOL(const char *tekst, ...)
622{
623 USHORT sel = RestoreOS2FS();
624 va_list argptr;
625
626 ODIN_HEAPCHECK();
627
628 if(!init)
629 {
630 init = TRUE;
631
632#ifdef DEFAULT_LOGGING_OFF
633 if(getenv("WIN32LOG_ENABLED")) {
634#else
635 if(!getenv("NOWIN32LOG")) {
636#endif
637 char logname[CCHMAXPATH];
638
639 sprintf(logname, "odin32_%d.log", getpid());
640 flog = fopen(logname, "w");
641 if(flog == NULL) {//probably running exe on readonly device
642 sprintf(logname, "%sodin32_%d.log", kernel32Path, getpid());
643 flog = fopen(logname, "w");
644 }
645 }
646 else
647 fLogging = FALSE;
648 }
649
650 if(fLogging && flog && (dwEnableLogging > 0))
651 {
652 TEB *teb = GetThreadTEB();
653
654 va_start(argptr, tekst);
655 if(teb) {
656 teb->o.odin.logfile = (DWORD)flog;
657 }
658 vfprintf(flog, tekst, argptr);
659 if(teb) teb->o.odin.logfile = 0;
660 va_end(argptr);
661 }
662 SetFS(sel);
663 return 1;
664}
665//******************************************************************************
666//******************************************************************************
667void SYSTEM DecreaseLogCount()
668{
669 dwEnableLogging--;
670}
671//******************************************************************************
672//******************************************************************************
673void SYSTEM IncreaseLogCount()
674{
675 dwEnableLogging++;
676}
677//******************************************************************************
678//******************************************************************************
679int SYSTEM WritePrivateLog(void *logfile, const char *tekst, ...)
680{
681 USHORT sel = RestoreOS2FS();
682 va_list argptr;
683
684 if(fLogging && logfile)
685 {
686 TEB *teb = GetThreadTEB();
687
688 va_start(argptr, tekst);
689 if(teb) {
690 teb->o.odin.logfile = (DWORD)flog;
691 }
692 vfprintf((FILE *)logfile, tekst, argptr);
693 if(teb) teb->o.odin.logfile = 0;
694 va_end(argptr);
695
696 if(tekst[strlen(tekst)-1] != '\n')
697 fprintf((FILE *)logfile, "\n");
698 }
699
700 SetFS(sel);
701 return 1;
702}
703//******************************************************************************
704//WriteLog has to take special care to handle dprintfs inside our os/2 exception
705//handler; if an exception occurs inside a dprintf, using dprintf in the exception
706//handler will hang the process
707//******************************************************************************
708int LogException(int state, int prevlock)
709{
710 TEB *teb = GetThreadTEB();
711 int ret = 0;
712
713 if (!teb) return 0;
714
715#if !defined(__EMX__)
716 if (teb->o.odin.logfile)
717 {
718#if (__IBMCPP__ == 300) || (__IBMC__ == 300)
719 PUSHORT lock = (USHORT *)(teb->o.odin.logfile+0x1C);
720#else
721#if __IBMC__ >= 360 || __IBMCPP__ >= 360
722//TODO: test this!!!!!!!
723 PUSHORT lock = (USHORT *)(teb->o.odin.logfile+0x1C);
724#else
725#error Check the offset of the lock count word in the file stream structure for this compiler revision!!!!!
726#endif
727#endif
728 ret = (*lock);
729 if (state == ENTER_EXCEPTION)
730 {
731 if((*lock) > 0) (*lock)--;
732 }
733 else
734 { //LEAVE_EXCEPTION
735 if(prevlock) (*lock)++;
736 }
737 }
738#else
739//kso 2001-01-29: EMX/GCC
740// we maybe should do something with the _more->rsem (_rmutex) structure but
741// I wanna have this compile, so we'll address problems later.
742#endif
743 return ret;
744}
745//******************************************************************************
746//Check if the exception occurred inside a fprintf (logging THDB member set)
747//If true, decrease the lock count for that file stream
748//NOTE: HACK: DEPENDS ON COMPILER VERSION!!!!
749//******************************************************************************
750void CheckLogException()
751{
752 TEB *teb = GetThreadTEB();
753 PUSHORT lock;
754
755 if(!teb) return;
756
757#if !defined(__EMX__)
758 if(teb->o.odin.logfile) {
759 //oops, exception in vfprintf; let's clear the lock count
760#if (__IBMCPP__ == 300) || (__IBMC__ == 300)
761 lock = (PUSHORT)(teb->o.odin.logfile+0x1C);
762#else
763#if __IBMC__ >= 360 || __IBMCPP__ >= 360
764//TODO: test this!!!!!!!
765 PUSHORT lock = (USHORT *)(teb->o.odin.logfile+0x1C);
766#else
767#error Check the offset of the lock count word in the file stream structure for this compiler revision!!!!!
768#endif
769#endif
770 (*lock)--;
771 }
772#else
773//kso 2001-01-29: EMX/GCC
774// we maybe should do something with the _more->rsem (_rmutex) structure but
775// I wanna have this compile, so we'll address problems later.
776#endif
777}
778//******************************************************************************
779//NOTE: No need to save/restore FS, as our FS selectors have already been
780// destroyed and FS == 0x150B.
781//******************************************************************************
782void CloseLogFile()
783{
784#ifdef __IBMC__
785 if(oldcrtmsghandle)
786 _set_crt_msg_handle(oldcrtmsghandle);
787#endif
788
789#ifdef WIN32_IP_LOGGING
790 if(logSocket != -1) {
791 soclose(logSocket);
792 }
793#endif
794
795 if(flog) fclose(flog);
796 flog = 0;
797}
798//******************************************************************************
799//Used to open any private logfiles used in kernel32 (for now only in winimagepeldr.cpp)
800//******************************************************************************
801void OpenPrivateLogFiles()
802{
803#ifdef DEFAULT_LOGGING_OFF
804 if(getenv("WIN32LOG_ENABLED")) {
805#else
806 if(!getenv("NOWIN32LOG")) {
807#endif
808 OpenPrivateLogFilePE();
809 }
810}
811//******************************************************************************
812//Used to close all private logfiles used in kernel32 (for now only in winimagepeldr.cpp)
813//******************************************************************************
814void ClosePrivateLogFiles()
815{
816#ifdef DEFAULT_LOGGING_OFF
817 if(getenv("WIN32LOG_ENABLED")) {
818#else
819 if(!getenv("NOWIN32LOG")) {
820#endif
821 ClosePrivateLogFilePE();
822 }
823}
824//******************************************************************************
825//******************************************************************************
826void SYSTEM CheckVersion(ULONG version, char *modname)
827{
828 dprintf(("CheckVersion of %s, %d\n", modname, version));
829 if(version != PE2LX_VERSION){
830 static char msg[300];
831 int r;
832 dprintf(("Version mismatch! %d, %d: %s\n", version, PE2LX_VERSION, modname));
833 sprintf(msg, "%s is intended for use with a different release of Odin.\n", modname);
834 do{
835 r = WinMessageBox(HWND_DESKTOP, NULLHANDLE, msg, "Version Mismatch!", 0, MB_ABORTRETRYIGNORE | MB_ICONEXCLAMATION | MB_MOVEABLE);
836 }while(r == MBID_RETRY); // giggle
837 if( r != MBID_IGNORE )
838 exit(987);
839 }
840}
841//******************************************************************************
842//******************************************************************************
843void SYSTEM CheckVersionFromHMOD(ULONG version, HMODULE hModule)
844{
845 char name[_MAX_PATH];
846
847 // query name of dll.
848 if(!DosQueryModuleName(hModule, sizeof(name), name))
849 CheckVersion(version, name);
850}
851//******************************************************************************
852//******************************************************************************
853#ifdef __WATCOMC__ /*PLF Sat 97-06-21 17:12:36*/
854 extern void interrupt3( void );
855 #pragma aux interrupt3= \
856 "int 3"
857#endif
858extern "C"
859void WIN32API DebugBreak()
860{
861 dprintf(("DebugBreak\n"));
862
863 LPSTR lpstrEnv = getenv("WIN32.DEBUGBREAK"); /* query environment */
864 if (lpstrEnv == NULL) /* if environment is not set, don't call debugger ! */
865 return;
866
867#ifdef __WATCOMC__
868 interrupt3();
869#else
870 _interrupt(3);
871#endif
872}
873//******************************************************************************
874//******************************************************************************
875
876
877/*****************************************************************************
878 * Name : DebugErrorBox
879 * Purpose : display an apprioriate error box with detailed information
880 * about the error cause
881 * Parameters: APIRET iErrorCode - OS/2 error code
882 * PSZ pszFormat - printf-format string
883 * ...
884 * Variables :
885 * Result : return code of the message box
886 * Remark :
887 * Status :
888 *
889 * Author : Patrick Haller [Tue, 1999/09/13 19:55]
890 *****************************************************************************/
891
892int SYSTEM DebugErrorBox(ULONG iErrorCode,
893 char* pszFormat,
894 ...)
895{
896 char szMessageBuffer[1024]; /* buffer for the text message */
897 char szErrorBuffer[1024]; /* buffer for the operating system text */
898 ULONG bc; /* dummy */
899 APIRET rc2; /* API returncode */
900 int iRC; /* message box return code */
901
902 USHORT sel = RestoreOS2FS();
903 va_list argptr;
904
905 // clear memory
906 memset (szMessageBuffer, 0, sizeof(szMessageBuffer));
907 memset (szErrorBuffer, 0, sizeof(szErrorBuffer));
908
909 // build message string
910 va_start(argptr, pszFormat);
911 vsprintf(szMessageBuffer, pszFormat, argptr);
912 va_end(argptr);
913
914 // query error string
915 rc2 = DosGetMessage(NULL,
916 0,
917 szErrorBuffer,
918 sizeof(szErrorBuffer),
919 iErrorCode,
920 "OSO001.MSG",
921 &bc);
922
923 // display message box
924 iRC = WinMessageBox(HWND_DESKTOP,
925 NULLHANDLE,
926 szMessageBuffer,
927 szErrorBuffer,
928 0,
929 MB_OK | MB_ICONEXCLAMATION | MB_MOVEABLE);
930 SetFS(sel);
931 return iRC;
932}
933
934
935/**
936 * Query Odin32 build number.
937 * @returns Build number.
938 * @status Completely implemented.
939 * @author knut st. osmundsen (knut.stange.osmundsen@mynd.no)
940 */
941int WIN32API Odin32GetBuildNumber(void)
942{
943 dprintf(("Odin32GetBuildNumber returned %d\n", ODIN32_BUILD_NR));
944 return ODIN32_BUILD_NR;
945}
946
Note: See TracBrowser for help on using the repository browser.