source: branches/gcc-kmk/src/kernel32/dbglog.cpp@ 21722

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

GCC doesn't have _set_crt_msg_handle().

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