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

Last change on this file since 21343 was 21343, checked in by vladest, 16 years ago
  1. Increased number of handles (4096 is not enougth for some Flash animations)
  2. Added CPU cycles couter for more accurate profiling
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(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(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(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, 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.