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

Last change on this file since 21302 was 21302, checked in by ydario, 16 years ago

Kernel32 updates.

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