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

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

Merge branch gcc-kmk to trunk.

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.