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

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

Use const char * for arguments accepting literal strings.

This is more correct and also clears GCC warnings.

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