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

Last change on this file since 21339 was 21339, checked in by vladest, 16 years ago
  1. Attempt to add support for DosAllocMem at specific address
  2. Fixed crashes in Handle manager when its tries to access non initialized pointer
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 = TRUE;
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.