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

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

Serialize each log statement using mutex.

This finally fixes the longstanding problem when multiple threads
intermix parts of their statements lines in the log file making it
totally unreadable.

File size: 31.6 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 VMutex logMutex;
304
305static void win32modname (ULONG eip, char *szModName, int cbModName)
306{
307 Win32ImageBase *pMod = NULL;
308 if (WinExe && WinExe->insideModule(eip))
309 pMod = WinExe;
310 else
311 pMod = Win32DllBase::findModuleByAddr(eip);
312 if (pMod != NULL)
313 {
314 szModName[0] = '\0';
315 strncat(szModName, pMod->getModuleName(), cbModName);
316 }
317}
318
319int SYSTEM WriteLog(const char *tekst, ...)
320{
321 USHORT sel = RestoreOS2FS();
322 va_list argptr;
323 TEB *teb = GetThreadTEB();
324
325 logMutex.enter();
326
327 pszLastLogEntry = tekst;
328
329 ODIN_HEAPCHECK();
330
331 if (!init)
332 {
333 init = TRUE;
334 firstTime = TRUE;
335
336#ifdef LOG_TIME
337 // initialize the current time counter
338 startTicks = GetTickCount();
339 SYSTEMTIME t;
340 GetLocalTime(&t);
341 startTime = t.wHour * 3600 + t.wMinute * 60 + t.wSecond;
342 startTime = (startTime * 1000) + t.wMilliseconds;
343#endif
344
345 if(getenv("WIN32LOG_FLUSHLINES"))
346 fFlushLines = TRUE;
347
348#ifdef DEFAULT_LOGGING_OFF
349 if(getenv("WIN32LOG_ENABLED"))
350 {
351#else
352 if(!getenv("NOWIN32LOG"))
353 {
354#endif
355#ifdef WIN32_IP_LOGGING
356 char *logserver = getenv("WIN32LOG_IPSERVER");
357 if(logserver) {
358 sock_init();
359
360 memset(&servername, 0, sizeof(servername));
361 servername.sin_family = AF_INET;
362 servername.sin_addr.s_addr = inet_addr(logserver);
363 servername.sin_port = WIN32_IP_LOG_PORT;
364
365 logSocket = socket(PF_INET, SOCK_DGRAM, 0);
366 }
367#endif
368 char szLogFile[CCHMAXPATH];
369 const char *pszLogBase = getenv("WIN32LOG_FILEBASE");
370 if (!pszLogBase)
371 pszLogBase = "odin32_";
372
373 sprintf(szLogFile, "%s%d.log", pszLogBase, getpid());
374 flog = fopen(szLogFile, "w");
375 if(flog == NULL)
376 {//probably running exe on readonly device
377 sprintf(szLogFile, "%sodin32_%d.log", kernel32Path, getpid());
378 flog = fopen(szLogFile, "w");
379 }
380#ifdef __IBMC__
381 oldcrtmsghandle = _set_crt_msg_handle(fileno(flog));
382#endif
383 }
384 else
385 fLogging = FALSE;
386
387 fDisableThread[0] = getenv("DISABLE_THREAD1") != NULL;
388 fDisableThread[1] = getenv("DISABLE_THREAD2") != NULL;
389 fDisableThread[2] = getenv("DISABLE_THREAD3") != NULL;
390 fDisableThread[3] = getenv("DISABLE_THREAD4") != NULL;
391 fDisableThread[4] = getenv("DISABLE_THREAD5") != NULL;
392 }
393
394 if (teb)
395 {
396 if(teb->o.odin.threadId < 5 && fDisableThread[teb->o.odin.threadId-1] == 1)
397 {
398 SetFS(sel);
399 logMutex.leave();
400 return 1;
401 }
402 }
403
404 if (!tekst)
405 {
406 if (flog)
407 fflush(flog);
408
409 SetFS(sel);
410 logMutex.leave();
411 return 1;
412 }
413
414#ifdef LOG_TIME
415 // get human readable time values
416 DWORD time = startTime + (GetTickCount() - startTicks);
417 DWORD h = (time / 3600000) % 24;
418 DWORD m = (time %= 3600000) / 60000;
419 DWORD s = (time %= 60000) / 1000;
420 DWORD ms = time % 1000;
421#endif
422
423 if (fLogging && flog && (dwEnableLogging > 0))
424 {
425 if (firstTime)
426 {
427 firstTime = FALSE;
428
429 // print the header with the legend
430#ifdef LOG_TIME
431 fprintf(flog,
432 " /--------------------- Thread ID\n"
433 " | /----------------- Call Depth\n"
434 " | | /-------------- Flags (O = OS/2 mode (FS=150B))\n"
435 " | | | /------- Current Time\n"
436 "--- --- - ------------\n");
437#else
438#ifdef SHOW_FPU_CONTROLREG
439 fprintf(flog,
440 " /------------ Thread ID\n"
441 " | /-------- Call Depth\n"
442 " | | /----- Flags (O = OS/2 mode (FS=150B))\n"
443 " | | | /-- FPU Control Register\n"
444 "--- --- - ---\n");
445#else
446 fprintf(flog,
447 " /-------- Thread ID\n"
448 " | /---- Call Depth\n"
449 " | | /- Flags (O = OS/2 mode (FS=150B))\n"
450 "--- --- -\n");
451#endif
452#endif
453 }
454
455 va_start(argptr, tekst);
456
457#ifdef WIN32_IP_LOGGING
458 if (logSocket == -1)
459 {
460#endif
461 if (teb)
462 {
463 ULONG ulCallDepth;
464#ifdef DEBUG
465 ulCallDepth = teb->o.odin.dbgCallDepth;
466#else
467 ulCallDepth = 0;
468#endif
469
470 teb->o.odin.logfile = (DWORD)flog;
471
472#ifdef LOG_TIME
473 fprintf(flog,
474 "t%02d %03d %c %02d:%02d:%02d.%03d: ",
475 LOWORD(teb->o.odin.threadId),
476 ulCallDepth,
477 (sel == 0x150b && fSwitchTIBSel) ? 'O' : '-',
478 h, m, s, ms);
479#else
480#ifdef SHOW_FPU_CONTROLREG
481 fprintf(flog,
482 "t%02d %03d %c %03X: ",
483 LOWORD(teb->o.odin.threadId),
484 ulCallDepth,
485 (sel == 0x150b && fSwitchTIBSel) ? 'O' : '-',
486 CONTROL87(0,0));
487#else
488 fprintf(flog,
489 "t%02d %03d %c: ",
490 LOWORD(teb->o.odin.threadId),
491 ulCallDepth,
492 (sel == 0x150b && fSwitchTIBSel) ? 'O' : '-');
493#endif
494#endif
495 }
496 else
497 {
498#ifdef LOG_TIME
499 fprintf(flog,
500 "t-- --- O %02d:%02d:%02d.%03d: ",
501 h, m, s, ms);
502#else
503#ifdef SHOW_FPU_CONTROLREG
504 fprintf(flog,
505 "t-- --- O ---: ");
506#else
507 fprintf(flog,
508 "t-- --- O: ");
509#endif
510#endif
511 }
512#ifdef WIN32_IP_LOGGING
513 }
514#endif
515
516#ifdef WIN32_IP_LOGGING
517 if(logSocket != -1)
518 {
519 char logbuffer[1024];
520 int prefixlen = 0;
521
522 if (teb)
523 {
524 ULONG ulCallDepth;
525#ifdef DEBUG
526 ulCallDepth = teb->o.odin.dbgCallDepth;
527#else
528 ulCallDepth = 0;
529#endif
530#ifdef LOG_TIME
531 sprintf(logbuffer,
532 "t%02d %03d %02d:%02d:%02d.%03d [%c]: ",
533 LOWORD(teb->o.odin.threadId),
534 ulCallDepth,
535 h, m, s, ms,
536 (sel == 0x150b && fSwitchTIBSel) ? 'O' : '.');
537#else
538 sprintf(logbuffer,
539 "t%02d %03d [%c]: ",
540 LOWORD(teb->o.odin.threadId),
541 ulCallDepth,
542 (sel == 0x150b && fSwitchTIBSel) ? 'O' : '.');
543#endif
544 prefixlen = strlen(logbuffer);
545 }
546
547 vsprintf(&logbuffer[prefixlen], tekst, argptr);
548
549 int rc;
550
551 servername.sin_family = AF_INET;
552 servername.sin_port = WIN32_IP_LOG_PORT;
553
554 rc = sendto(logSocket, logbuffer, strlen(logbuffer)+1, 0, (struct sockaddr *)&servername, sizeof(servername));
555 if (rc == -1)
556 rc = sock_errno();
557 if (teb)
558 teb->o.odin.logfile = 0;
559 va_end(argptr);
560 }
561 else
562 {
563 vfprintf(flog, tekst, argptr);
564 if (teb)
565 teb->o.odin.logfile = 0;
566 va_end(argptr);
567
568 if (tekst[strlen(tekst)-1] != '\n')
569 fprintf(flog, "\n");
570#if 0
571 if (teb && LOWORD(teb->o.odin.threadId) > 1)
572 {
573 TEB *winteb = GetThreadTEB();
574 PWINEXCEPTION_FRAME pframe = (PWINEXCEPTION_FRAME)winteb->except;
575
576 fprintf(flog, "debug Win32 exception chain %08X (%08X) (teb = %08X, esp = %08X)\n", pframe, QueryExceptionChain(), teb, getESP());
577 fprintf(flog, "Top record at %08X, Prev at %08X, handler at %08X\n", (PWINEXCEPTION_FRAME)QueryExceptionChain(), ((PWINEXCEPTION_FRAME)QueryExceptionChain())->Prev, ((PWINEXCEPTION_FRAME)QueryExceptionChain())->Handler);
578 fprintf(flog, "*teb %08X %08X %08X %08X %08X %08X %08X %08X\n",
579 ((ULONG *)teb)[0],((ULONG *)teb)[1],((ULONG *)teb)[2],((ULONG *)teb)[3],
580 ((ULONG *)teb)[4],((ULONG *)teb)[5],((ULONG *)teb)[6],((ULONG *)teb)[7]);
581 while ((pframe != NULL) && ((ULONG)pframe != 0xFFFFFFFF)) {
582 if ((void *)pframe > winteb->stack_top || (void *)pframe < winteb->stack_low)
583 {
584 fprintf(flog, "Chain corrupted! Record at %08X is outside stack boundaries!\n", pframe);
585 break;
586 }
587
588 if ((ULONG)pframe < getESP())
589 {
590 fprintf(flog, "Chain corrupted! Record at %08X is below stack pointer!\n", pframe);
591 break;
592 }
593
594 char szModName[32] = "";
595 char szModName2[32] = "";
596 win32modname ((ULONG)pframe->Handler, szModName, sizeof (szModName));
597 win32modname ((ULONG)pframe->Prev, szModName2, sizeof (szModName2));
598 fprintf(flog, "Record at %08X, Prev at %08X [%s], handler at %08X [%s]\n", pframe, pframe->Prev, szModName2, pframe->Handler, szModName);
599 if (pframe == pframe->Prev) {
600 fprintf(flog, "Chain corrupted! Record at %08X pointing to itself!\n", pframe);
601 break;
602 }
603 pframe = pframe->Prev;
604 }
605 }
606#endif
607 if (fFlushLines)
608 fflush(flog);
609 }
610#else
611 vfprintf(flog, tekst, argptr);
612 if(teb) teb->o.odin.logfile = 0;
613 va_end(argptr);
614
615 if(tekst[strlen(tekst)-1] != '\n')
616 fprintf(flog, "\n");
617
618 if(fFlushLines)
619 fflush(flog);
620#endif
621 }
622
623 SetFS(sel);
624 logMutex.leave();
625 return 1;
626}
627//******************************************************************************
628//******************************************************************************
629int SYSTEM WriteLogNoEOL(const char *tekst, ...)
630{
631 USHORT sel = RestoreOS2FS();
632 va_list argptr;
633
634 logMutex.enter();
635
636 ODIN_HEAPCHECK();
637
638 if (!init)
639 {
640 init = TRUE;
641
642#ifdef DEFAULT_LOGGING_OFF
643 if(getenv("WIN32LOG_ENABLED"))
644 {
645#else
646 if (!getenv("NOWIN32LOG"))
647 {
648#endif
649 char logname[CCHMAXPATH];
650
651 sprintf(logname, "odin32_%d.log", getpid());
652 flog = fopen(logname, "w");
653 if(flog == NULL) {//probably running exe on readonly device
654 sprintf(logname, "%sodin32_%d.log", kernel32Path, getpid());
655 flog = fopen(logname, "w");
656 }
657 }
658 else
659 fLogging = FALSE;
660 }
661
662 if (fLogging && flog && (dwEnableLogging > 0))
663 {
664 TEB *teb = GetThreadTEB();
665
666 va_start(argptr, tekst);
667 if (teb)
668 teb->o.odin.logfile = (DWORD)flog;
669 vfprintf(flog, tekst, argptr);
670 if (teb)
671 teb->o.odin.logfile = 0;
672 va_end(argptr);
673 }
674
675 SetFS(sel);
676 logMutex.leave();
677 return 1;
678}
679//******************************************************************************
680//******************************************************************************
681void SYSTEM DecreaseLogCount()
682{
683 dwEnableLogging--;
684}
685//******************************************************************************
686//******************************************************************************
687void SYSTEM IncreaseLogCount()
688{
689 dwEnableLogging++;
690}
691//******************************************************************************
692//******************************************************************************
693int SYSTEM WritePrivateLog(void *logfile, const char *tekst, ...)
694{
695 USHORT sel = RestoreOS2FS();
696 va_list argptr;
697
698 if (fLogging && logfile)
699 {
700 TEB *teb = GetThreadTEB();
701
702 va_start(argptr, tekst);
703 if (teb)
704 teb->o.odin.logfile = (DWORD)flog;
705 vfprintf((FILE *)logfile, tekst, argptr);
706 if (teb)
707 teb->o.odin.logfile = 0;
708 va_end(argptr);
709
710 if (tekst[strlen(tekst)-1] != '\n')
711 fprintf((FILE *)logfile, "\n");
712 }
713
714 SetFS(sel);
715 return 1;
716}
717//******************************************************************************
718//WriteLog has to take special care to handle dprintfs inside our os/2 exception
719//handler; if an exception occurs inside a dprintf, using dprintf in the exception
720//handler will hang the process
721//******************************************************************************
722int LogException(int state, int prevlock)
723{
724 TEB *teb = GetThreadTEB();
725 int ret = 0;
726
727 if (!teb) return 0;
728
729#if !defined(__EMX__)
730 if (teb->o.odin.logfile)
731 {
732#if (__IBMCPP__ == 300) || (__IBMC__ == 300)
733 PUSHORT lock = (USHORT *)(teb->o.odin.logfile+0x1C);
734#else
735#if __IBMC__ >= 360 || __IBMCPP__ >= 360
736//TODO: test this!!!!!!!
737 PUSHORT lock = (USHORT *)(teb->o.odin.logfile+0x1C);
738#else
739#error Check the offset of the lock count word in the file stream structure for this compiler revision!!!!!
740#endif
741#endif
742 ret = (*lock);
743 if (state == ENTER_EXCEPTION)
744 {
745 if((*lock) > 0) (*lock)--;
746 }
747 else
748 { //LEAVE_EXCEPTION
749 if(prevlock) (*lock)++;
750 }
751 }
752#else
753//kso 2001-01-29: EMX/GCC
754// we maybe should do something with the _more->rsem (_rmutex) structure but
755// I wanna have this compile, so we'll address problems later.
756#endif
757 return ret;
758}
759//******************************************************************************
760//Check if the exception occurred inside a fprintf (logging THDB member set)
761//If true, decrease the lock count for that file stream
762//NOTE: HACK: DEPENDS ON COMPILER VERSION!!!!
763//******************************************************************************
764void CheckLogException()
765{
766 TEB *teb = GetThreadTEB();
767 PUSHORT lock;
768
769 if(!teb) return;
770
771#if !defined(__EMX__)
772 if(teb->o.odin.logfile) {
773 //oops, exception in vfprintf; let's clear the lock count
774#if (__IBMCPP__ == 300) || (__IBMC__ == 300)
775 lock = (PUSHORT)(teb->o.odin.logfile+0x1C);
776#else
777#if __IBMC__ >= 360 || __IBMCPP__ >= 360
778//TODO: test this!!!!!!!
779 PUSHORT lock = (USHORT *)(teb->o.odin.logfile+0x1C);
780#else
781#error Check the offset of the lock count word in the file stream structure for this compiler revision!!!!!
782#endif
783#endif
784 (*lock)--;
785 }
786#else
787//kso 2001-01-29: EMX/GCC
788// we maybe should do something with the _more->rsem (_rmutex) structure but
789// I wanna have this compile, so we'll address problems later.
790#endif
791}
792//******************************************************************************
793//NOTE: No need to save/restore FS, as our FS selectors have already been
794// destroyed and FS == 0x150B.
795//******************************************************************************
796void CloseLogFile()
797{
798#ifdef __IBMC__
799 if(oldcrtmsghandle)
800 _set_crt_msg_handle(oldcrtmsghandle);
801#endif
802
803#ifdef WIN32_IP_LOGGING
804 if(logSocket != -1) {
805 soclose(logSocket);
806 }
807#endif
808
809 if(flog) fclose(flog);
810 flog = 0;
811}
812//******************************************************************************
813//Used to open any private logfiles used in kernel32 (for now only in winimagepeldr.cpp)
814//******************************************************************************
815void OpenPrivateLogFiles()
816{
817#ifdef DEFAULT_LOGGING_OFF
818 if(getenv("WIN32LOG_ENABLED")) {
819#else
820 if(!getenv("NOWIN32LOG")) {
821#endif
822 OpenPrivateLogFilePE();
823 }
824}
825//******************************************************************************
826//Used to close all private logfiles used in kernel32 (for now only in winimagepeldr.cpp)
827//******************************************************************************
828void ClosePrivateLogFiles()
829{
830#ifdef DEFAULT_LOGGING_OFF
831 if(getenv("WIN32LOG_ENABLED")) {
832#else
833 if(!getenv("NOWIN32LOG")) {
834#endif
835 ClosePrivateLogFilePE();
836 }
837}
838//******************************************************************************
839//******************************************************************************
840void SYSTEM CheckVersion(ULONG version, char *modname)
841{
842 dprintf(("CheckVersion of %s, %d\n", modname, version));
843 if(version != PE2LX_VERSION){
844 static char msg[300];
845 int r;
846 dprintf(("Version mismatch! %d, %d: %s\n", version, PE2LX_VERSION, modname));
847 sprintf(msg, "%s is intended for use with a different release of Odin.\n", modname);
848 do{
849 r = WinMessageBox(HWND_DESKTOP, NULLHANDLE, msg, "Version Mismatch!", 0, MB_ABORTRETRYIGNORE | MB_ICONEXCLAMATION | MB_MOVEABLE);
850 }while(r == MBID_RETRY); // giggle
851 if( r != MBID_IGNORE )
852 exit(987);
853 }
854}
855//******************************************************************************
856//******************************************************************************
857void SYSTEM CheckVersionFromHMOD(ULONG version, HMODULE hModule)
858{
859 char name[_MAX_PATH];
860
861 // query name of dll.
862 if(!DosQueryModuleName(hModule, sizeof(name), name))
863 CheckVersion(version, name);
864}
865//******************************************************************************
866//******************************************************************************
867#ifdef __WATCOMC__ /*PLF Sat 97-06-21 17:12:36*/
868 extern void interrupt3( void );
869 #pragma aux interrupt3= \
870 "int 3"
871#endif
872extern "C"
873void WIN32API DebugBreak()
874{
875 dprintf(("DebugBreak\n"));
876
877 LPSTR lpstrEnv = getenv("WIN32.DEBUGBREAK"); /* query environment */
878 if (lpstrEnv == NULL) /* if environment is not set, don't call debugger ! */
879 return;
880
881#ifdef __WATCOMC__
882 interrupt3();
883#else
884 _interrupt(3);
885#endif
886}
887//******************************************************************************
888//******************************************************************************
889
890
891/*****************************************************************************
892 * Name : DebugErrorBox
893 * Purpose : display an apprioriate error box with detailed information
894 * about the error cause
895 * Parameters: APIRET iErrorCode - OS/2 error code
896 * PSZ pszFormat - printf-format string
897 * ...
898 * Variables :
899 * Result : return code of the message box
900 * Remark :
901 * Status :
902 *
903 * Author : Patrick Haller [Tue, 1999/09/13 19:55]
904 *****************************************************************************/
905
906int SYSTEM DebugErrorBox(ULONG iErrorCode,
907 char* pszFormat,
908 ...)
909{
910 char szMessageBuffer[1024]; /* buffer for the text message */
911 char szErrorBuffer[1024]; /* buffer for the operating system text */
912 ULONG bc; /* dummy */
913 APIRET rc2; /* API returncode */
914 int iRC; /* message box return code */
915
916 USHORT sel = RestoreOS2FS();
917 va_list argptr;
918
919 // clear memory
920 memset (szMessageBuffer, 0, sizeof(szMessageBuffer));
921 memset (szErrorBuffer, 0, sizeof(szErrorBuffer));
922
923 // build message string
924 va_start(argptr, pszFormat);
925 vsprintf(szMessageBuffer, pszFormat, argptr);
926 va_end(argptr);
927
928 // query error string
929 rc2 = DosGetMessage(NULL,
930 0,
931 szErrorBuffer,
932 sizeof(szErrorBuffer),
933 iErrorCode,
934 "OSO001.MSG",
935 &bc);
936
937 // display message box
938 iRC = WinMessageBox(HWND_DESKTOP,
939 NULLHANDLE,
940 szMessageBuffer,
941 szErrorBuffer,
942 0,
943 MB_OK | MB_ICONEXCLAMATION | MB_MOVEABLE);
944 SetFS(sel);
945 return iRC;
946}
947
948
949/**
950 * Query Odin32 build number.
951 * @returns Build number.
952 * @status Completely implemented.
953 * @author knut st. osmundsen (knut.stange.osmundsen@mynd.no)
954 */
955int WIN32API Odin32GetBuildNumber(void)
956{
957 dprintf(("Odin32GetBuildNumber returned %d\n", ODIN32_BUILD_NR));
958 return ODIN32_BUILD_NR;
959}
960
Note: See TracBrowser for help on using the repository browser.