source: trunk/src/kernel32/dbglog.cpp

Last change on this file was 22041, checked in by dmik, 13 years ago

kernel32: Add public debug log lock/unlock methods for higher level serialization.

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