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

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

Use pid instead of the ordinal number in log file names.

This in particular fixes the problem when WGSS50 writes to the log
before the ordinal is correctly initialized by KERNEL32 which resulted
into two processes writing to the same log file.

This also guarantees that a subsequent re-run will not vanish the
previous log file which is also useful sometimes.

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