source: trunk/src/kernel32/_ras.cpp

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

Merge branch gcc-kmk to trunk.

  • Property svn:eol-style set to native
File size: 46.1 KB
RevLine 
[21302]1#define INCL_BASE
2#define INCL_WIN
3#define INCL_WINERRORS
4#define INCL_DOSFILEMGR
5#include <os2wrap.h> // Odin32 OS/2 api wrappers
6
7#include <_ras.h>
8#include <umalloc.h>
[21916]9#include <process.h>
[21302]10
11#include <custombuild.h>
12#include <odincrt.h>
[21916]13#ifdef __GNUC__
14#include <float.h>
15#else
[21342]16#include <libc/float.h>
[21916]17#endif
[21302]18
19#include "initterm.h"
20
21#define DBG_LOCALLOG DBG__ras
22#include "dbglocal.h"
23
24/* RAS functions to isolate all RAS related services:
[21916]25 *
[21302]26 * - Common statistic functions to track objects allocations/deallocations.
27 *
28 * - RAS event logging.
29 *
30 * - RAS plugin support.
31 *
32 * Is to be used by all Odin subsystems by calling the KERNEL32 exports.
33 *
34 * Note: RAS subsystem does not use any other Odin subsystem, and IMO must not.
35 * That is RAS has its own heap, serialization, logging.
[21916]36 * External stuff that is used:
[21302]37 * - from Odin: asm helpers from interlock.asm
38 * - from libc: uheap functions
[21916]39 *
[21302]40 * The following has been borrowed from other Odin parts and adapted:
41 * - critical section
42 * - shared heap
43 *
44 * Note2: Currently RAS subsystem works on per process basis.
45 * This can be changed if there will be a need to have
46 * shared RAS subsystem for different processes.
47 * The code has some support for this.
48 *
49 * Note3: RAS subsystem works with OS/2 fs value. Current fs is saved
50 * and restored at each public function.
51 */
52
53typedef struct _RAS_TRACK RAS_TRACK;
54
[21916]55typedef struct _RAS_OBJECT_INFO
[21302]56{
57 struct _RAS_OBJECT_INFO *next;
58 struct _RAS_OBJECT_INFO *prev;
[21916]59
[21302]60 RAS_TRACK_HANDLE h;
[21916]61
[21302]62 ULONG objident;
63 ULONG usecount;
[21916]64
[21302]65 ULONG objhandle;
[21916]66
[21302]67 void *objdata;
68 ULONG cbobjdata;
[21916]69
[21302]70 char userdata[1];
71} RAS_OBJECT_INFO;
72
73struct _RAS_TRACK
74{
75 struct _RAS_TRACK *next;
76 struct _RAS_TRACK *prev;
77
78 RAS_OBJECT_INFO *objfirst;
79 RAS_OBJECT_INFO *objlast;
[21916]80
[21302]81 char objname[80];
[21916]82
[21302]83 ULONG cbuserdata;
[21916]84
[21302]85 ULONG fLogObjectContent: 1;
86 ULONG fMemory: 1;
87 ULONG fLogAtExit: 1;
88 ULONG fLogObjectsAtExit: 1;
[21916]89
[21302]90 FNLOC *pfnLogObjectContent;
91 FNCOC *pfnCompareObjectContent;
[21916]92
[21302]93 /* Used when fMemory = 1 for RasTrackAlloc, Realloc and Free calls */
94 ULONG cAllocs;
95 ULONG cFrees;
96 ULONG cbTotalAllocated;
[21916]97
[21302]98};
99
100typedef struct _CRITICAL_SECTION_RAS
101{
102 LONG LockCount;
103 LONG RecursionCount;
104 ULONG OwningThread;
105 HEV hevLock;
106} CRITICAL_SECTION_RAS;
107
108
109typedef struct _RAS_CONFIG
110{
111 ULONG ulTimeout; // RAS critical section timeout
112 ULONG ulInitHeapSize;
113 ULONG fDumpHeapObjects: 1;
114 ULONG fUseHighMem: 1;
115 ULONG fRasEnable: 1;
116 ULONG fRasBreakPoint: 1;
117} RAS_CONFIG;
118
119typedef struct _RasLogChannel
120{
121 FNWL *pfnWriteLog; // function to write ras string to log
122 FNOLF *pfnOpenLogFile;
123 FNCLF *pfnCloseLogFile;
124
125 ULONG hlogfile; // filehandle if default logging functions are used
[21916]126
[21302]127 HMODULE hmod;
128} RasLogChannel;
129
130typedef struct _RAS_DATA
131{
132 HMODULE hmod; // handle of this dll
[21916]133
[21302]134 RasLogChannel rlc;
[21916]135
[21302]136 Heap_t rasheap;
137 void *pHeapMem;
138 ULONG ulRefCount;
139 ULONG flAllocMem;
[21916]140
[21302]141 HMODULE hmodPlugin;
[21916]142
[21302]143 RasEntryTable ret;
144 RasPluginEntryTable pet;
145
146 struct _RAS_TRACK *firsttrack;
147 struct _RAS_TRACK *lasttrack;
148
149 RAS_TRACK_HANDLE h; // current handle, set by ENTER_RAS
150
151 ULONG fNoEOL: 1;
152} RAS_DATA;
153
154
155int rasInitialized = 0;
156
157CRITICAL_SECTION_RAS csras = { -1, 0, 0, 0 };
158RAS_CONFIG rascfg;
159RAS_DATA rasdata;
160
161
162/* Private functions */
163
164typedef struct _RASCONTEXT_I
165{
166 USHORT fs;
167 USHORT cw;
168} RASCONTEXT_I;
169
[21916]170extern "C" {
171
[21302]172void rasSaveContext(RASCONTEXT_I *pcontext)
173{
174 pcontext->fs = RestoreOS2FS ();
175 pcontext->cw = _control87(0, 0);
176}
177
178void rasRestoreContext(RASCONTEXT_I *pcontext)
179{
180 _control87(pcontext->cw, 0xFFFF);
181 SetFS (pcontext->fs);
182}
183
184ULONG rasGetCurrentThreadId (void)
185{
186 PTIB ptib;
187 PPIB ppib;
188
189 DosGetInfoBlocks(&ptib, &ppib);
[21916]190
[21302]191 return ppib->pib_ulpid << 16 | ptib->tib_ptib2->tib2_ultid;
192}
193
194ULONG rasInitializeCriticalSection (CRITICAL_SECTION_RAS *crit)
195{
196 int rc = NO_ERROR;
[21916]197
[21302]198 rc = DosCreateEventSem (NULL, &crit->hevLock, DC_SEM_SHARED, 0);
[21916]199
[21302]200 if (rc != NO_ERROR)
201 {
202 crit->hevLock = 0;
203 }
[21916]204
[21302]205 return rc;
206}
207
208void rasUninitializeCriticalSection (CRITICAL_SECTION_RAS *crit)
209{
210 DosCloseEventSem (crit->hevLock);
211}
212
213ULONG rasEnterCriticalSection (CRITICAL_SECTION_RAS *crit, ULONG ulTimeout)
214{
215 APIRET rc = NO_ERROR;
[21916]216
[21302]217 ULONG threadid = rasGetCurrentThreadId ();
[21916]218
[21302]219 // We want to acquire the section, count the entering
220 DosInterlockedIncrement (&crit->LockCount);
[21916]221
[21302]222 if (crit->OwningThread == threadid)
223 {
224 // This thread already owns the section
225 crit->RecursionCount++;
226 return NO_ERROR;
227 }
228
229 // try to acquire the section
230 for (;;)
231 {
232 // try to assign owning thread id atomically
233 if (DosInterlockedCompareExchange((PLONG)&crit->OwningThread, threadid, 0) == 0)
234 {
235 break;
236 }
[21916]237
[21302]238 rc = DosWaitEventSem (crit->hevLock, ulTimeout);
[21916]239
240 if (rc != NO_ERROR)
[21302]241 {
242 // We fail, deregister itself
243 DosInterlockedDecrement (&crit->LockCount);
244 return rc;
245 }
246 }
[21916]247
[21302]248 // the section was successfully aquired
249 crit->RecursionCount = 1;
[21916]250
[21302]251 return NO_ERROR;
252}
253
254
255ULONG rasLeaveCriticalSection (CRITICAL_SECTION_RAS *crit)
256{
257 if (crit->OwningThread != rasGetCurrentThreadId ())
258 {
259 return ERROR_INVALID_PARAMETER;
260 }
261
262 if (--crit->RecursionCount)
263 {
264 DosInterlockedDecrement (&crit->LockCount);
[21916]265
[21302]266 return NO_ERROR;
267 }
[21916]268
[21302]269 crit->OwningThread = 0;
270
271 if (DosInterlockedDecrement (&crit->LockCount) >= 0)
272 {
273 ULONG ulnrposts = 0;
274
275 DosPostEventSem (crit->hevLock);
276
277 DosResetEventSem (crit->hevLock, &ulnrposts);
278 }
[21916]279
[21302]280 return NO_ERROR;
281}
282
283void EnterSerializeRAS (void)
284{
285 rasEnterCriticalSection (&csras, rascfg.ulTimeout);
286}
287
288void ExitSerializeRAS (void)
289{
290 rasLeaveCriticalSection (&csras);
291}
292
293/* Private logging functions */
294void ulong2string (unsigned long number, char *string, int n, int base)
295{
[21916]296 static const char *digits = "0123456789ABCDEF";
297
[21302]298 unsigned long tmp = number;
299 char *s = string;
300 int len = 0;
301 int l = 0;
302 int i;
[21916]303
[21302]304 if (n <= 0)
305 {
306 return;
307 }
[21916]308
[21302]309 if (tmp == 0)
310 {
311 s[l++] = digits[0];
312 }
[21916]313
[21302]314 while (tmp != 0)
315 {
316 if (l >= n)
317 {
318 break;
319 }
320 s[l++] = digits[tmp%base];
321 len++;
322 tmp /= base;
323 }
324 if (l < n)
325 {
326 s[l++] = '\0';
327 }
[21916]328
[21302]329 s = string;
[21916]330
[21302]331 for (i = 0; i < len/2; i++)
332 {
333 tmp = s[i];
334 s[i] = s[len - i - 1];
335 s[len - i - 1] = tmp;
336 }
337
338 return;
339}
340
341void long2string (long number, char *string, int n, int base)
342{
343 if (n <= 0)
344 {
345 return;
346 }
[21916]347
[21302]348 if (number < 0)
349 {
350 *string++ = '-';
351 number = -number;
352 n--;
353 }
[21916]354
[21302]355 ulong2string (number, string, n, base);
356}
[21916]357
[21302]358int string2ulong (const char *string, char **pstring2, unsigned long *pvalue, int base)
359{
360 unsigned long value = 0;
361 int sign = 1;
[21916]362
[21302]363 const char *p = string;
[21916]364
[21302]365 if (p[0] == '-')
366 {
367 sign = -1;
368 p++;
369 }
[21916]370
[21302]371 if (base == 0)
372 {
373 if (p[0] == 0 && (p[1] == 'x' || p[1] == 'X'))
374 {
375 base = 16;
376 p += 2;
377 }
378 else if (p[0] == 0)
379 {
380 base = 8;
381 p += 1;
382 }
383 else
384 {
385 base = 10;
386 }
387 }
[21916]388
[21302]389 while (*p)
390 {
391 int digit = 0;
[21916]392
[21302]393 if ('0' <= *p && *p <= '9')
394 {
395 digit = *p - '0';
396 }
397 else if ('a' <= *p && *p <= 'f')
398 {
399 digit = *p - 'a' + 0xa;
400 }
401 else if ('A' <= *p && *p <= 'F')
402 {
403 digit = *p - 'A' + 0xa;
404 }
405 else
406 {
407 break;
408 }
[21916]409
[21302]410 if (digit >= base)
411 {
412 break;
413 }
[21916]414
[21302]415 value = value*base + digit;
[21916]416
[21302]417 p++;
418 }
[21916]419
[21302]420 if (pstring2)
421 {
422 *pstring2 = (char *)p;
423 }
[21916]424
[21302]425 *pvalue = sign*value;
[21916]426
[21302]427 return 1;
428}
429
[21916]430#ifndef __GNUC__
431
[21302]432int vsnprintf (char *buf, int n, const char *fmt, va_list args)
433{
434 int count = 0;
435 char *s = (char *)fmt;
436 char *d = buf;
[21916]437
[21302]438 if (n <= 0)
439 {
440 return 0;
441 }
[21916]442
[21302]443 n--;
[21916]444
[21302]445 while (*s && count < n)
446 {
447 char tmpstr[16];
[21916]448
[21302]449 char *str = NULL;
[21916]450
[21302]451 int width = 0;
452 int precision = 0;
[21916]453
[21302]454 if (*s == '%')
455 {
456 s++;
[21916]457
[21302]458 if ('0' <= *s && *s <= '9' || *s == '-')
459 {
460 char setprec = (*s == '0');
461 string2ulong (s, &s, (unsigned long *)&width, 10);
462 if (setprec)
463 {
464 precision = width;
465 }
466 }
467
468 if (*s == '.')
469 {
470 s++;
471 string2ulong (s, &s, (unsigned long *)&precision, 10);
472 }
[21916]473
[21302]474 if (*s == 's')
475 {
476 str = va_arg(args, char *);
477 s++;
478 precision = 0;
479 }
480 else if (*s == 'c')
481 {
482 tmpstr[0] = va_arg(args, int);
483 tmpstr[1] = 0;
484 str = &tmpstr[0];
485 s++;
486 precision = 0;
487 }
488 else if (*s == 'p' || *s == 'P')
489 {
490 int num = va_arg(args, int);
[21916]491
[21302]492 ulong2string (num, tmpstr, sizeof (tmpstr), 16);
[21916]493
[21302]494 str = &tmpstr[0];
495 s++;
496 width = 8;
497 precision = 8;
498 }
499 else
500 {
501 if (*s == 'l')
502 {
503 s++;
504 }
[21916]505
[21302]506 if (*s == 'd' || *s == 'i')
507 {
508 int num = va_arg(args, int);
[21916]509
[21302]510 long2string (num, tmpstr, sizeof (tmpstr), 10);
[21916]511
[21302]512 str = &tmpstr[0];
513 s++;
514 }
515 else if (*s == 'u')
516 {
517 int num = va_arg(args, int);
[21916]518
[21302]519 ulong2string (num, tmpstr, sizeof (tmpstr), 10);
[21916]520
[21302]521 str = &tmpstr[0];
522 s++;
523 }
524 else if (*s == 'x' || *s == 'X')
525 {
526 int num = va_arg(args, int);
[21916]527
[21302]528 ulong2string (num, tmpstr, sizeof (tmpstr), 16);
[21916]529
[21302]530 str = &tmpstr[0];
531 s++;
532 }
533 }
534 }
[21916]535
[21302]536 if (str != NULL)
537 {
538 int i;
539 char numstr[16];
540 int len = strlen (str);
541 int leftalign = 0;
[21916]542
[21302]543 if (width < 0)
544 {
545 width = -width;
546 leftalign = 1;
547 }
[21916]548
[21302]549 if (precision)
550 {
551 i = 0;
552 while (precision > len)
553 {
554 numstr[i++] = '0';
555 precision--;
556 }
[21916]557
[21302]558 memcpy (&numstr[i], str, len);
[21916]559
[21302]560 str = &numstr[0];
561 len += i;
562 }
[21916]563
[21302]564 if (len < width && !leftalign)
565 {
566 while (len < width && count < n)
567 {
568 *d++ = ' ';
569 width--;
570 count++;
571 }
[21916]572
[21302]573 if (count >= n)
574 {
575 break;
576 }
577 }
[21916]578
[21302]579 i = 0;
580 while (i < len && count < n)
581 {
582 *d++ = str[i++];
583 count++;
584 }
[21916]585
[21302]586 if (count >= n)
587 {
588 break;
589 }
[21916]590
[21302]591 if (len < width && leftalign)
592 {
593 while (len < width && count < n)
594 {
595 *d++ = ' ';
596 width--;
597 count++;
598 }
[21916]599
[21302]600 if (count >= n)
601 {
602 break;
603 }
604 }
605 }
606 else
607 {
608 *d++ = *s++;
609 count++;
610 }
611 }
[21916]612
[21302]613 *d = '\0';
[21916]614
[21302]615 return count + 1;
616}
617
[21916]618#endif // ifndef __GNUC__
619
620#ifdef __GNUC__
621int WIN32API_VA ras_snprintf (char *buf, int n, const char *fmt, ...)
622#else
[21302]623int WIN32API snprintf (char *buf, int n, const char *fmt, ...)
[21916]624#endif
[21302]625{
626 va_list args;
[21916]627
[21302]628 int rc = 0;
629
630 va_start (args, fmt);
[21916]631
[21302]632 rc = vsnprintf (buf, n, fmt, args);
633
634 va_end (args);
[21916]635
[21302]636 return rc;
637}
638
639int WIN32API rasOpenLogFile (ULONG *ph, const char *logfilename)
640{
641 ULONG ulAction = 0;
[21916]642
[21302]643 int rc = DosOpen (logfilename, ph, &ulAction, 0L, FILE_ARCHIVED,
644 OPEN_ACTION_CREATE_IF_NEW | OPEN_ACTION_REPLACE_IF_EXISTS,
645 OPEN_FLAGS_NOINHERIT | OPEN_SHARE_DENYNONE |
646 OPEN_ACCESS_READWRITE, 0L);
[21916]647
[21302]648 if (rc == ERROR_TOO_MANY_OPEN_FILES)
649 {
650 LONG lReqCount = 10l;
651 ULONG ulCurMaxFH = 0ul;
[21916]652
[21302]653 DosSetRelMaxFH (&lReqCount, &ulCurMaxFH);
[21916]654
[21302]655 rc = DosOpen (logfilename, ph, &ulAction, 0L, FILE_ARCHIVED,
656 OPEN_ACTION_CREATE_IF_NEW | OPEN_ACTION_REPLACE_IF_EXISTS,
657 OPEN_FLAGS_NOINHERIT | OPEN_SHARE_DENYNONE |
658 OPEN_ACCESS_READWRITE, 0L);
659 }
[21916]660
[21302]661 if (rc != NO_ERROR)
662 {
663 *ph = -1;
664 }
[21916]665
[21302]666 return rc;
667}
668
669void WIN32API rasCloseLogFile (ULONG h)
670{
671 DosClose ((HFILE)h);
672}
673
674void WIN32API rasWriteLog (ULONG h, char *msg, ULONG len)
675{
676 ULONG ulActual = 0;
[21916]677
[21302]678 DosWrite ((HFILE)h, msg, len, &ulActual);
679}
680
681void rasCloseLogChannel (RasLogChannel *prlc)
682{
683 if (prlc->hlogfile != -1)
684 {
685 prlc->pfnCloseLogFile (prlc->hlogfile);
686 prlc->hlogfile = -1;
687 }
[21916]688
[21302]689 if (prlc->hmod)
690 {
691 DosFreeModule (prlc->hmod);
692 prlc->hmod = NULLHANDLE;
693 }
[21916]694
[21302]695 prlc->pfnWriteLog = NULL;
696 prlc->pfnOpenLogFile = NULL;
697 prlc->pfnCloseLogFile = NULL;
698}
699
700int rasOpenLogChannel (const char *env_loghandler, RasLogChannel *prlc,
701 const char *filename)
702{
703 int rc = NO_ERROR;
[21916]704
[21302]705 const char *env = NULL;
[21916]706
[21302]707 DosScanEnv (env_loghandler, &env);
[21916]708
[21302]709 HMODULE hmod = NULLHANDLE;
[21916]710
[21302]711 PFN popenlogfile = NULL;
712 PFN pcloselogfile = NULL;
713 PFN pwritelog = NULL;
[21916]714
[21302]715 if (env)
716 {
717 rc = DosLoadModule (NULL, 0, env, &hmod);
[21916]718
[21302]719 if (rc == NO_ERROR)
720 {
721 rc = DosQueryProcAddr (hmod, 0, "WIN32RAS_OPENLOGFILE", &popenlogfile);
722 }
[21916]723
[21302]724 if (rc == NO_ERROR)
725 {
726 rc = DosQueryProcAddr (hmod, 0, "WIN32RAS_CLOSELOGFILE", &pcloselogfile);
727 }
[21916]728
[21302]729 if (rc == NO_ERROR)
730 {
731 rc = DosQueryProcAddr (hmod, 0, "WIN32RAS_WRITELOG", &pwritelog);
732 }
[21916]733
[21302]734 if (rc != NO_ERROR && hmod)
735 {
736 DosFreeModule (hmod);
737 hmod = NULLHANDLE;
738 }
739 }
[21916]740
[21302]741 if (rc == NO_ERROR && hmod && popenlogfile && pcloselogfile && pwritelog)
742 {
743 prlc->pfnWriteLog = (FNWL *)pwritelog;
744 prlc->pfnOpenLogFile = (FNOLF *)popenlogfile;
745 prlc->pfnCloseLogFile = (FNCLF *)pcloselogfile;
746 prlc->hlogfile = -1;
747 prlc->hmod = hmod;
748 }
749 else
750 {
751 prlc->pfnWriteLog = rasWriteLog;
752 prlc->pfnOpenLogFile = rasOpenLogFile;
753 prlc->pfnCloseLogFile = rasCloseLogFile;
754 prlc->hlogfile = -1;
755 prlc->hmod = NULLHANDLE;
[21916]756
[21302]757 rc = NO_ERROR;
758 }
[21916]759
[21302]760 rc = prlc->pfnOpenLogFile (&prlc->hlogfile, filename);
[21916]761
[21302]762 if (rc != NO_ERROR)
763 {
764 prlc->hlogfile = -1;
765 rasCloseLogChannel (prlc);
766 }
[21916]767
[21302]768 return rc;
769}
770
771int rasInitializeLog (void)
772{
773 int rc = NO_ERROR;
[21916]774
[21302]775 const char *filename = "win32ras.log";
[21916]776
[21302]777 const char *env = NULL;
[21916]778
[21302]779 DosScanEnv ("WIN32RAS_LOG_FILENAME", &env);
[21916]780
[21302]781 if (env)
782 {
783 filename = env;
784 }
[21916]785
[21302]786 char uniqueLogFileName[260];
[21916]787
[21302]788 snprintf (uniqueLogFileName, sizeof(uniqueLogFileName),
[21916]789 "%s.%d", filename, getpid());
790
[21302]791 if (rasdata.rlc.hlogfile == -1)
792 {
793 rc = rasOpenLogChannel ("WIN32RAS_LOGHANDLER", &rasdata.rlc, uniqueLogFileName);
794 }
[21916]795
[21302]796 return rc;
797}
798
799void rasUninitializeLog (void)
800{
801 rasCloseLogChannel (&rasdata.rlc);
802}
803
[21916]804void rasLogInternalV (RAS_LOG_CHANNEL_H hchannel, const char *fmt, va_list args)
[21302]805{
806 static char szOutMsg[4096];
807
808 ULONG ulHdrLen = snprintf (szOutMsg, sizeof (szOutMsg), "%s", "");
[21916]809
[21302]810 ulHdrLen -= 1;
[21916]811
[21302]812 ULONG ulMsgLen = vsnprintf (&szOutMsg[ulHdrLen], sizeof (szOutMsg) - ulHdrLen, fmt, args);
813
814 ulMsgLen -= 1;
[21916]815
[21302]816 if (ulMsgLen > 0)
817 {
818 if (!rasdata.fNoEOL)
819 {
820 if (szOutMsg[ulMsgLen + ulHdrLen - 1] != '\n')
821 {
822 szOutMsg[ulMsgLen + ulHdrLen] = '\n';
823 szOutMsg[ulMsgLen + ulHdrLen + 1] = '\0';
824 ulMsgLen++;
825 }
826 }
[21916]827
[21302]828 RasLogChannel *prlc = hchannel? (RasLogChannel *)hchannel: &rasdata.rlc;
[21916]829
[21302]830 prlc->pfnWriteLog (prlc->hlogfile, szOutMsg, ulMsgLen + ulHdrLen);
831 }
832}
833
[21916]834void rasLog (const char *fmt, ...)
[21302]835{
836 va_list args;
837
838 va_start (args, fmt);
[21916]839
[21302]840 rasLogInternalV (NULL, fmt, args);
[21916]841
[21302]842 va_end (args);
843}
844
[21916]845void rasLogInternal (const char *fmt, ...)
[21302]846{
847 va_list args;
848
849 va_start (args, fmt);
[21916]850
[21302]851 rasLogInternalV (NULL, fmt, args);
[21916]852
[21302]853 va_end (args);
854}
855
[21916]856void WIN32API_VA rasLogExternal (const char *fmt, ...)
[21302]857{
858 va_list args;
859
860 USHORT sel = RestoreOS2FS();
861
862 va_start (args, fmt);
[21916]863
[21302]864 rasLogInternalV (NULL, fmt, args);
[21916]865
[21302]866 va_end (args);
[21916]867
[21302]868 SetFS (sel);
869}
870
871/* Private heap functions */
872#ifndef PAG_ANY
873 #define PAG_ANY 0x00000400
874#endif
875
876#ifndef QSV_VIRTUALADDRESSLIMIT
877 #define QSV_VIRTUALADDRESSLIMIT 30
878#endif
879
880static int privateRefCount = 0;
881
882void * _LNK_CONV getmore_fn (Heap_t heap, size_t *size, int *clean)
883{
884 APIRET rc;
885 void *p;
886
887 rasLog ("RAS heap: getmore_fn(%08xh, %08xh, %08xh)\n", heap, *size, *clean);
888
889 /* round the size up to a multiple of 64K */
890 *size = (*size + 0x10000) & 0xFFFF0000ul;
891
892 *clean = _BLOCK_CLEAN;
[21916]893
[21302]894 rc = DosAllocSharedMem (&p, NULL, *size, rasdata.flAllocMem | OBJ_GETTABLE);
[21916]895
[21302]896 if (rc != NO_ERROR)
897 {
898 rasLog ("RAS heap: getmore_fn: DosAllocSharedMem failed, rc = %d\n", rc);
899 }
[21916]900
[21302]901 return p;
902}
903
904void _LNK_CONV release_fn (Heap_t heap, void *block, size_t size)
905{
906 DosFreeMem (block);
907}
908
909int rasInitializeHeap (void)
910{
911 int rc = NO_ERROR;
912
913 // necessary until next WGSS update
914 if (++privateRefCount > 1)
915 {
916 rasLog ("RAS heap initialization: privateRefCount = %d\n", privateRefCount);
917 return NO_ERROR;
918 }
919
920 if (rasdata.pHeapMem == NULL)
921 {
922 rasdata.flAllocMem = PAG_READ | PAG_WRITE | PAG_COMMIT;
[21916]923
[21302]924 if (rascfg.fUseHighMem)
925 {
926 ULONG ulSysinfo = 0;
[21916]927
[21302]928 rc = DosQuerySysInfo (QSV_VIRTUALADDRESSLIMIT, QSV_VIRTUALADDRESSLIMIT, &ulSysinfo, sizeof (ulSysinfo));
[21916]929
[21302]930 if (rc == NO_ERROR && ulSysinfo > 512) // VirtualAddresslimit is in MB
931 {
932 rasdata.flAllocMem |= PAG_ANY;
[21916]933
[21302]934 rasLog ("RAS heap initialization: will use high memory\n");
935 }
936 }
937
[21916]938 rc = DosAllocSharedMem (&rasdata.pHeapMem, NULL, rascfg.ulInitHeapSize,
[21302]939 rasdata.flAllocMem | OBJ_GETTABLE);
940 if (rc != NO_ERROR)
941 {
942 rasLog ("RAS heap initialization: DosAllocSharedMem failed %d\n", rc);
943 return NO_ERROR;
944 }
[21916]945
946 rasdata.rasheap = _ucreate (rasdata.pHeapMem, rascfg.ulInitHeapSize,
[21302]947 _BLOCK_CLEAN, _HEAP_REGULAR | _HEAP_SHARED,
948 getmore_fn, release_fn);
949
950 if (rasdata.rasheap == NULL)
951 {
952 rasLog ("RAS heap initialization: _ucreate failed\n");
[21916]953
[21302]954 DosFreeMem (rasdata.pHeapMem);
955 rasdata.pHeapMem = NULL;
[21916]956
[21302]957 return ERROR_NOT_ENOUGH_MEMORY;
958 }
959 }
960 else
961 {
962 /* Not sure that this is really necessary, VAC heap probably
963 * takes care of this in _uopen.
964 */
965 rc = DosGetSharedMem (rasdata.pHeapMem, rasdata.flAllocMem);
[21916]966
[21302]967 if (rc != NO_ERROR)
968 {
969 rasLog ("RAS heap initialization: DosGetSharedMem failed %d\n", rc);
[21916]970
[21302]971 return rc;
972 }
973
974 if (_uopen (rasdata.rasheap) != 0)
975 {
976 rasLog ("RAS heap initialization: _uopen failed\n");
[21916]977
[21302]978 DosFreeMem (rasdata.pHeapMem);
[21916]979
[21302]980 return ERROR_NOT_ENOUGH_MEMORY;
981 }
982 }
[21916]983
[21302]984 rasdata.ulRefCount++;
[21916]985
[21302]986 return NO_ERROR;
987}
988
989int _LNK_CONV callback_fn (const void *pentry, size_t sz, int useflag, int status,
990 const char *filename, size_t line)
991{
992 if (_HEAPOK != status)
993 {
994 rasLog ("status is not _HEAPOK: %d\n", status);
995 return 1;
996 }
[21916]997
998 if (useflag == _USEDENTRY)
[21302]999 {
1000 if (filename)
1001 {
1002 rasLog ("%08x %u at %s %d\n", pentry, sz, filename, line);
1003 }
1004 else
1005 {
1006 rasLog ("%08x %u\n", pentry, sz);
1007 }
1008 }
1009
1010 return 0;
1011}
1012
1013void rasUninitializeHeap (void)
1014{
1015 if (--privateRefCount > 0)
1016 {
1017 rasLog ("RAS heap uninitialization: privateRefCount = %d\n", privateRefCount);
[21916]1018
[21302]1019 return;
1020 }
1021
1022 if (--rasdata.ulRefCount == 0)
1023 {
1024 if (rasdata.rasheap)
1025 {
1026 if (rascfg.fDumpHeapObjects)
1027 {
1028 rasLog ("Dumping used RAS heap objects:\n");
1029 _uheap_walk (rasdata.rasheap, callback_fn);
1030 rasLog ("Used RAS heap objects dump completed.\n");
1031 }
1032
1033 _uclose (rasdata.rasheap);
[21916]1034
[21302]1035 _udestroy (rasdata.rasheap, _FORCE);
1036 rasdata.rasheap = NULL;
1037 }
[21916]1038
[21302]1039 if (rasdata.pHeapMem)
1040 {
1041 DosFreeMem (rasdata.pHeapMem);
1042 rasdata.pHeapMem = NULL;
1043 }
1044 }
[21916]1045 else
[21302]1046 {
1047 _uclose (rasdata.rasheap);
1048 }
1049}
1050
1051void *rasAlloc (ULONG size)
1052{
1053 void *p = _umalloc(rasdata.rasheap, size);
[21916]1054
[21302]1055 if (p)
1056 {
1057 memset (p, 0, size);
1058 }
1059 else
1060 {
1061 rasLog ("RAS heap: allocation failed, %d bytes\n", size);
1062 }
[21916]1063
[21302]1064 return p;
1065}
1066
1067void rasFree (void *p)
1068{
1069 free (p);
1070}
1071
1072/* Private object manipulation functions */
1073
1074RAS_TRACK_HANDLE rasVerifyTrackHandle (RAS_TRACK_HANDLE h)
1075{
1076 RAS_TRACK_HANDLE iter = rasdata.firsttrack;
[21916]1077
[21302]1078 while (iter)
1079 {
1080 if (iter == h)
1081 {
1082 break;
1083 }
[21916]1084
[21302]1085 iter = iter->next;
1086 }
[21916]1087
[21302]1088 return iter;
1089}
1090
1091ULONG rasGenObjIdent (void)
1092{
[21916]1093 static ULONG objident = 0;
1094
[21302]1095 objident++;
[21916]1096
[21302]1097 if (objident == 0)
1098 {
1099 objident++;
1100 }
[21916]1101
[21302]1102 return objident;
1103}
1104
1105int rasAddObjectInfo (RAS_OBJECT_INFO *pinfo, RAS_TRACK_HANDLE h, RAS_OBJECT_INFO *pinfo_next)
1106{
1107 if (h->objfirst)
1108 {
1109 pinfo->next = h->objfirst;
1110 h->objfirst->prev = pinfo;
1111 h->objfirst = pinfo;
1112 }
1113 else
1114 {
1115 h->objlast = h->objfirst = pinfo;
1116 }
[21916]1117
[21302]1118 return NO_ERROR;
1119}
[21916]1120
[21302]1121void rasRemoveObjectInfo (RAS_OBJECT_INFO *pinfo)
1122{
1123 if (pinfo->next)
1124 {
1125 pinfo->next->prev = pinfo->prev;
1126 }
1127 else
1128 {
1129 // this was last object
1130 pinfo->h->objlast = pinfo->prev;
1131 }
[21916]1132
[21302]1133 if (pinfo->prev)
1134 {
1135 pinfo->prev->next = pinfo->next;
1136 }
1137 else
1138 {
1139 // This was the first object.
1140 pinfo->h->objfirst = pinfo->next;
1141 }
1142}
1143
1144void rasInitObjectInfo (RAS_OBJECT_INFO *pinfo, RAS_TRACK_HANDLE h,
1145 ULONG objhandle, void *objdata, ULONG cbobjdata)
1146{
1147 pinfo->objhandle = objhandle;
[21916]1148
[21302]1149 pinfo->h = h;
[21916]1150
[21302]1151 pinfo->usecount = 1;
[21916]1152
[21302]1153 pinfo->objident = rasGenObjIdent ();
1154
1155 if (h->fLogObjectContent)
1156 {
1157 if (objdata && cbobjdata > 0)
1158 {
1159 pinfo->objdata = &pinfo->userdata[h->cbuserdata];
1160 memcpy (pinfo->objdata, objdata, cbobjdata);
1161 }
1162 }
[21916]1163
[21302]1164 pinfo->cbobjdata = cbobjdata;
1165}
1166
1167struct _RAS_OBJECT_INFO *rasSearchObject2 (RAS_TRACK_HANDLE h, ULONG objident)
1168{
[21916]1169 if (!h)
[21302]1170 {
1171 return NULL;
1172 }
1173
1174 RAS_OBJECT_INFO *iter = h->objfirst;
[21916]1175
[21302]1176 while (iter)
1177 {
1178 if (iter->objident == objident)
1179 {
1180 break;
1181 }
1182 iter = iter->next;
1183 }
[21916]1184
[21302]1185 return iter;
1186}
1187
1188/* Fast object search function that WILL use some kind ob binary search
1189 * in object linked list. To achieve this the list of cource must be sorted
1190 * and this function also WILL return proposed place for a new object
1191 * in ppinfo_next (object next to searched one, would the serached object
1192 * in the list already). rasAddObjectInfo WILL then takes use the *ppinfo_next
1193 * to insert the object in right place in the list.
1194 */
1195
1196struct _RAS_OBJECT_INFO *rasSearchObject (RAS_TRACK_HANDLE h, ULONG objhandle, RAS_OBJECT_INFO **ppinfo_next)
1197{
[21916]1198 if (!h)
[21302]1199 {
1200 return NULL;
1201 }
1202
1203 RAS_OBJECT_INFO *iter = h->objfirst;
[21916]1204
[21302]1205 while (iter)
1206 {
1207 if (iter->objhandle == objhandle)
1208 {
1209 break;
1210 }
[21916]1211
[21302]1212 iter = iter->next;
1213 }
[21916]1214
[21302]1215 if (iter && ppinfo_next)
1216 {
1217 *ppinfo_next = iter->next;
1218 }
[21916]1219
[21302]1220 return iter;
1221}
1222
1223void rasIncUseCount (RAS_OBJECT_INFO *pinfo)
1224{
1225 pinfo->usecount++;
1226}
1227
1228int rasDecUseCount (RAS_OBJECT_INFO *pinfo)
1229{
1230 pinfo->usecount--;
[21916]1231
[21302]1232 return pinfo->usecount;
1233}
1234
1235ULONG WIN32API rasLogObjectContent (ULONG objident, ULONG objhandle, void *objdata, ULONG cbobjdata, FNRASLOG_EXTERNAL *pRasLog)
1236{
1237 int i;
1238 char buf[128];
1239 char *p = &buf[0];
[21916]1240
[21302]1241 if (!objdata)
1242 {
1243 return NO_ERROR;
1244 }
[21916]1245
[21302]1246 for (i = 0; i < cbobjdata; i++)
1247 {
1248 if (i % 16 == 0)
1249 {
1250 if (i > 0)
1251 {
1252 pRasLog ("%s\n", buf);
1253 p = &buf[0];
1254 }
[21916]1255
[21302]1256 snprintf (p, sizeof(buf) - (p - &buf[0]), "%8.8x:", i / 16);
1257 p += strlen (p);
1258 }
[21916]1259
[21302]1260 snprintf (p, sizeof(buf) - (p - &buf[0]), " %2.2x", ((char *)objdata)[i]);
1261 p += strlen (p);
1262 }
[21916]1263
[21302]1264 pRasLog ("%s\n", buf);
[21916]1265
[21302]1266 return NO_ERROR;
1267}
1268
1269ULONG WIN32API rasCompareObjectContent (ULONG objhandle, void *objdata1, ULONG cbobjdata1, void *objdata2, ULONG cbobjdata2)
1270{
1271 if (cbobjdata1 != cbobjdata2)
1272 {
1273 return 1;
1274 }
[21916]1275
[21302]1276 if (objdata1 == NULL || objdata2 == NULL)
1277 {
1278 // can't compare, assume they are not equal
1279 return 1;
1280 }
[21916]1281
[21302]1282 return memcmp (objdata1, objdata2, cbobjdata1);
1283}
1284
[21916]1285ULONG rasCallLogObjectContent (RAS_TRACK_HANDLE h, RASCONTEXT_I *pctx,
1286 ULONG objident, ULONG objhandle,
[21302]1287 void *objdata, ULONG cbobjdata, FNRASLOG_EXTERNAL *rasLogExternal)
1288{
1289 rasRestoreContext (pctx);
[21916]1290
[21302]1291 ULONG rc = h->pfnLogObjectContent (objident, objhandle, objdata, cbobjdata, rasLogExternal);
[21916]1292
[21302]1293 rasSaveContext (pctx);
[21916]1294
[21302]1295 return rc;
1296}
1297
[21916]1298ULONG WIN32API rasCallCompareObjectContent (RAS_TRACK_HANDLE h, RASCONTEXT_I *pctx,
[21302]1299 ULONG objhandle, void *objdata1, ULONG cbobjdata1, void *objdata2, ULONG cbobjdata2)
1300{
1301 rasRestoreContext (pctx);
[21916]1302
[21302]1303 ULONG rc = h->pfnCompareObjectContent (objhandle, objdata1, cbobjdata1, objdata2, cbobjdata2);
[21916]1304
[21302]1305 rasSaveContext (pctx);
[21916]1306
[21302]1307 return rc;
1308}
1309
1310void WIN32API _RasEntry (ULONG ulEvent, void *p, ULONG cb)
1311{
1312 return;
1313}
1314
1315void rasQueryEnvUlong (const char *name, ULONG *pul, ULONG min, ULONG max, ULONG mult)
1316{
1317 const char *env = NULL;
[21916]1318
[21302]1319 DosScanEnv (name, &env);
[21916]1320
[21302]1321 if (env)
1322 {
1323 ULONG ul = 0;
1324 char *e = NULL;
[21916]1325
[21302]1326 string2ulong (env, &e, &ul, 10);
[21916]1327
[21302]1328 if (e && *e == '\0')
1329 {
1330 if (min <= ul && ul <= max)
1331 {
1332 *pul = ul * mult;
1333 }
1334 }
1335 }
1336}
1337
1338int rasInitializePlugin (void)
1339{
1340 int rc = NO_ERROR;
[21916]1341
[21302]1342 if (!rasdata.hmodPlugin)
1343 {
1344 rasdata.ret.cb = sizeof (RasEntryTable);
[21916]1345
[21302]1346 rasdata.ret.RasRegisterObjectTracking = RasRegisterObjectTracking;
1347 rasdata.ret.RasDeregisterObjectTracking = RasDeregisterObjectTracking;
1348 rasdata.ret.RasAddObject = RasAddObject;
1349 rasdata.ret.RasRemoveObject = RasRemoveObject;
1350 rasdata.ret.RasSetObjectUserData = RasSetObjectUserData;
1351 rasdata.ret.RasQueryObjectUserData = RasQueryObjectUserData;
1352 rasdata.ret.RasEnterSerialize = RasEnterSerialize;
1353 rasdata.ret.RasExitSerialize = RasExitSerialize;
1354 rasdata.ret.RasOpenLogChannel = RasOpenLogChannel;
1355 rasdata.ret.RasWriteLogChannel = RasWriteLogChannel;
1356 rasdata.ret.RasCloseLogChannel = RasCloseLogChannel;
1357 rasdata.ret.RasLog = RasLog2;
1358 rasdata.ret.RasLogNoEOL = RasLogNoEOL2;
1359 rasdata.ret.RasLogMsg = RasLogMsg2;
[21916]1360#ifdef __GNUC__
1361 rasdata.ret.snprintf = ras_snprintf;
1362#else
[21302]1363 rasdata.ret.snprintf = snprintf;
[21916]1364#endif
[21302]1365 rasdata.ret.RasSaveContext = RasSaveContext;
1366 rasdata.ret.RasRestoreContext = RasRestoreContext;
1367 rasdata.ret.RasSetProcAddr = RasSetProcAddr;
1368 rasdata.ret.RasGetModuleHandle = RasGetModuleHandle;
1369 rasdata.ret.RasCountObjects = RasCountObjects;
1370 rasdata.ret.RasTrackMemAlloc = RasTrackMemAlloc;
1371 rasdata.ret.RasTrackMemRealloc = RasTrackMemRealloc;
1372 rasdata.ret.RasTrackMemFree = RasTrackMemFree;
1373 rasdata.ret.RasGetTrackHandle = RasGetTrackHandle;
[21916]1374
[21302]1375 rasdata.pet.cb = sizeof (RasPluginEntryTable);
[21916]1376
[21302]1377 rasdata.pet.RasEntry = _RasEntry;
1378
1379 const char *env = NULL;
[21916]1380
[21302]1381 DosScanEnv ("WIN32RAS_PLUGIN", &env);
[21916]1382
[21302]1383 if (env)
1384 {
1385 HMODULE hmod = NULLHANDLE;
1386 FNPI *pfnPluginInit = NULL;
[21916]1387
[21302]1388 rc = DosLoadModule (NULL, 0, env, &hmod);
[21916]1389
[21302]1390 if (rc == NO_ERROR)
1391 {
1392 rc = DosQueryProcAddr (hmod, 0, "WIN32RAS_PLUGIN_INIT", (PFN *)&pfnPluginInit);
1393 }
[21916]1394
[21302]1395 if (rc != NO_ERROR)
1396 {
1397 rasLogInternal ("Could not load RAS plugin %s rc = %d", env, rc);
1398 }
[21916]1399
[21302]1400 if (rc != NO_ERROR && hmod)
1401 {
1402 DosFreeModule (hmod);
1403 }
1404 else
1405 {
1406 rasdata.hmodPlugin = hmod;
[21916]1407
[21302]1408 pfnPluginInit (rasdata.hmod, &rasdata.ret, &rasdata.pet);
1409 }
1410 }
1411 }
[21916]1412
[21302]1413 return rc;
1414}
1415
1416int rasUninitializePlugin (void)
1417{
1418 int rc = NO_ERROR;
[21916]1419
[21302]1420 if (rasdata.hmodPlugin)
1421 {
1422 HMODULE hmod = rasdata.hmodPlugin;
1423 FNPE *pfnPluginExit = NULL;
[21916]1424
[21302]1425 rc = DosQueryProcAddr (hmod, 0, "WIN32RAS_PLUGIN_EXIT", (PFN *)&pfnPluginExit);
[21916]1426
[21302]1427 if (rc == NO_ERROR)
1428 {
1429 pfnPluginExit (rasdata.hmod);
1430 }
[21916]1431
[21302]1432 DosFreeModule (hmod);
1433 }
[21916]1434
[21302]1435 return rc;
1436}
1437
1438/* Public RAS functions entry/exit sequences */
1439
1440#define NO_HANDLE ((RAS_TRACK_HANDLE)-1)
1441
1442#define ENTER_RAS_RET(a, b) \
1443 if (!a || !rascfg.fRasEnable) return b; \
1444 RAS_TRACK_HANDLE old_rasdata_h = rasdata.h; \
1445 RASCONTEXT_I ctx; \
1446 rasSaveContext (&ctx); \
1447 do { \
1448 EnterSerializeRAS (); \
1449 if (a != NO_HANDLE) rasdata.h = a; \
1450 } while (0)
1451
1452#define ENTER_RAS(a) \
1453 if (!a || !rascfg.fRasEnable) return; \
1454 RAS_TRACK_HANDLE old_rasdata_h = rasdata.h; \
1455 RASCONTEXT_I ctx; \
1456 rasSaveContext (&ctx); \
1457 do { \
1458 EnterSerializeRAS (); \
1459 if (a != NO_HANDLE) rasdata.h = a; \
1460 } while (0)
1461
1462#define ENTER_RAS_NO_RESTORE() \
1463 do { \
1464 if (rascfg.fRasEnable) EnterSerializeRAS ();\
1465 } while (0)
1466
1467#define EXIT_RAS() do { \
1468 rasRestoreContext (&ctx); \
1469 rasdata.h = old_rasdata_h; \
1470 ExitSerializeRAS (); \
1471 } while (0)
1472
1473#define EXIT_RAS_NO_RESTORE() do { \
1474 if (rascfg.fRasEnable) ExitSerializeRAS ();\
1475 } while (0)
1476
1477
1478
1479/* Exported functions */
1480
1481int WIN32API RasInitialize (HMODULE hmod)
1482{
1483 int rc = NO_ERROR;
[21916]1484
[21302]1485 if (!rasInitialized)
1486 {
1487 rasInitialized = 1;
[21916]1488
[21302]1489 memset (&rascfg, 0, sizeof (rascfg));
[21916]1490
[21302]1491 rascfg.ulTimeout = 60000; // default 1 minute
1492 rasQueryEnvUlong ("WIN32RAS_TIMEOUT", &rascfg.ulTimeout, 1, 3600, 1000);
[21916]1493
[21302]1494 rascfg.ulInitHeapSize = 128*1024;
1495 rasQueryEnvUlong ("WIN32RAS_INITHEAPSIZE", &rascfg.ulInitHeapSize, 64, 16*1024, 1024);
[21916]1496
[21302]1497 ULONG ul = 0;
1498 rasQueryEnvUlong ("WIN32RAS_DUMPHEAPOBJECTS", &ul, 0, 1, 1);
1499 rascfg.fDumpHeapObjects = ul;
[21916]1500
[21302]1501 ul = 1;
1502 rasQueryEnvUlong ("WIN32RAS_USEHIGHMEM", &ul, 0, 1, 1);
1503 rascfg.fUseHighMem = ul;
[21916]1504
[21302]1505 ul = 0;
1506 rasQueryEnvUlong ("WIN32RAS_ENABLE", &ul, 0, 1, 1);
1507 rascfg.fRasEnable = ul;
[21916]1508
[21302]1509 ul = 0;
1510 rasQueryEnvUlong ("WIN32RAS_BREAKPOINT", &ul, 0, 1, 1);
1511 rascfg.fRasBreakPoint = ul;
[21916]1512
[21302]1513 memset (&rasdata, 0, sizeof (rasdata));
1514 rasdata.rlc.hlogfile = -1;
1515 rasdata.hmod = hmod;
[21916]1516
[21302]1517 rc = NO_ERROR;
1518 }
[21916]1519
[21302]1520 if (!rascfg.fRasEnable)
1521 {
1522 return rc;
1523 }
1524
1525 if (rascfg.fRasBreakPoint)
1526 {
1527 _interrupt(3);
1528 }
1529
1530 rc = rasInitializeLog ();
[21916]1531
[21302]1532 if (rc == NO_ERROR)
1533 {
1534 rc = rasInitializeCriticalSection (&csras);
1535 }
[21916]1536
[21302]1537 if (rc == NO_ERROR)
1538 {
1539 rc = rasInitializeHeap ();
1540 }
[21916]1541
[21302]1542 if (rc == NO_ERROR)
1543 {
1544 rc = rasInitializePlugin ();
1545 }
[21916]1546
[21302]1547 return rc;
1548}
1549
1550void WIN32API RasUninitialize (void)
1551{
1552 ENTER_RAS(NO_HANDLE);
[21916]1553
[21302]1554 /* Deregister all objects */
1555 while (rasdata.firsttrack)
1556 {
1557 RAS_TRACK_HANDLE iter = rasdata.firsttrack;
[21916]1558
[21302]1559 if (iter->fLogAtExit)
1560 {
1561 RasLogObjects (iter, iter->fLogObjectsAtExit? RAS_FLAG_LOG_OBJECTS: 0);
1562 }
[21916]1563
[21302]1564 RasDeregisterObjectTracking (iter);
[21916]1565
[21302]1566 rasFree (iter);
1567 }
[21916]1568
[21302]1569 rasUninitializePlugin ();
[21916]1570
[21302]1571 rasUninitializeHeap ();
[21916]1572
[21302]1573 EXIT_RAS();
[21916]1574
[21302]1575 rasUninitializeCriticalSection (&csras);
[21916]1576
1577 rasUninitializeLog ();
[21302]1578}
1579
1580RAS_TRACK_HANDLE WIN32API RasGetTrackHandle (const char *objname)
1581{
1582 ENTER_RAS_RET(NO_HANDLE, NULL);
[21916]1583
[21302]1584 RAS_TRACK_HANDLE iter = rasdata.firsttrack;
[21916]1585
[21302]1586 while (iter)
1587 {
1588 if (stricmp (objname, iter->objname) == 0)
1589 {
1590 break;
1591 }
[21916]1592
[21302]1593 iter = iter->next;
1594 }
[21916]1595
[21302]1596 EXIT_RAS();
[21916]1597
[21302]1598 return iter;
1599}
1600
[21916]1601void WIN32API RasRegisterObjectTracking (RAS_TRACK_HANDLE *ph, const char *objname,
[21302]1602 ULONG cbuserdata,
1603 ULONG flags,
1604 FNLOC *pfnLogObjectContent,
1605 FNCOC *pfnCompareObjectContent)
1606{
1607 ENTER_RAS(NO_HANDLE);
[21916]1608
[21302]1609 RAS_TRACK *prt = (RAS_TRACK *)rasAlloc (sizeof (RAS_TRACK));
[21916]1610
[21302]1611 if (prt)
1612 {
1613 strcpy (prt->objname, objname);
[21916]1614
[21302]1615 prt->cbuserdata = cbuserdata;
[21916]1616
[21302]1617 if (flags & RAS_TRACK_FLAG_LOGOBJECTCONTENT)
1618 {
1619 prt->fLogObjectContent = 1;
1620 }
[21916]1621
[21302]1622 if (flags & RAS_TRACK_FLAG_MEMORY)
1623 {
1624 prt->fMemory = 1;
1625 }
[21916]1626
[21302]1627 if (flags & RAS_TRACK_FLAG_LOG_AT_EXIT)
1628 {
1629 prt->fLogAtExit = 1;
1630 }
[21916]1631
[21302]1632 if (flags & RAS_TRACK_FLAG_LOG_OBJECTS_AT_EXIT)
1633 {
1634 prt->fLogObjectsAtExit = 1;
1635 }
[21916]1636
[21302]1637 if (pfnLogObjectContent)
1638 {
1639 prt->pfnLogObjectContent = pfnLogObjectContent;
1640 }
1641 else
1642 {
1643 prt->pfnLogObjectContent = rasLogObjectContent;
1644 }
[21916]1645
[21302]1646 if (pfnCompareObjectContent)
1647 {
1648 prt->pfnCompareObjectContent = pfnCompareObjectContent;
1649 }
1650 else
1651 {
1652 prt->pfnCompareObjectContent = pfnCompareObjectContent;
1653 }
[21916]1654
[21302]1655 /* Insert the new tracking record in the list */
1656 if (rasdata.firsttrack)
1657 {
1658 prt->next = rasdata.firsttrack;
1659 rasdata.firsttrack->prev = prt;
1660 rasdata.firsttrack = prt;
1661 }
1662 else
1663 {
1664 rasdata.lasttrack = rasdata.firsttrack = prt;
1665 }
[21916]1666
[21302]1667 *ph = prt;
1668 }
1669
1670 EXIT_RAS();
1671}
1672
1673void WIN32API RasDeregisterObjectTracking (RAS_TRACK_HANDLE h)
1674{
1675 ENTER_RAS (h);
1676
1677 h = rasVerifyTrackHandle (h);
[21916]1678
[21302]1679 if (h)
1680 {
1681 /* Remove all objects */
1682 while (h->objfirst)
1683 {
1684 RAS_OBJECT_INFO *iter = h->objfirst;
[21916]1685
[21302]1686 rasRemoveObjectInfo (iter);
[21916]1687
[21302]1688 rasFree (iter);
1689 }
[21916]1690
[21302]1691 /* Remove the track record */
1692 if (h->next)
1693 {
1694 h->next->prev = h->prev;
1695 }
1696 else
1697 {
1698 // this was last tracking record
1699 rasdata.lasttrack = h->prev;
1700 }
[21916]1701
[21302]1702 if (h->prev)
1703 {
1704 h->prev->next = h->next;
1705 }
1706 else
1707 {
1708 // This was the first track record
1709 rasdata.firsttrack = h->next;
1710 }
1711 }
[21916]1712
[21302]1713 EXIT_RAS ();
1714}
1715
1716/* Add a new object in list of tracked ones. */
1717ULONG WIN32API RasAddObject (RAS_TRACK_HANDLE h, ULONG objhandle,
1718 void *objdata, ULONG cbobjdata)
1719{
1720 ENTER_RAS_RET (h, 0);
[21916]1721
[21302]1722 struct _RAS_OBJECT_INFO *pinfo_next = NULL;
[21916]1723
[21302]1724 struct _RAS_OBJECT_INFO *pinfo = rasSearchObject (h, objhandle, &pinfo_next);
[21916]1725
[21302]1726// rasLog ("Object added: handle = %8.8X\n", objhandle);
[21916]1727
[21302]1728 if (pinfo != NULL)
1729 {
1730 /* Object already in the list. Normally that should not happen and is
1731 * probably an indication of some problems with the caller's subsystem.
1732 * The subsystem will take this into account by incrementing use count
1733 * for this object.
1734 */
1735 rasIncUseCount (pinfo);
[21916]1736
[21302]1737 /* log this event */
1738 rasLog ("Dublicate object added: handle = %8.8X\n", objhandle);
1739 if (h->fLogObjectContent)
1740 {
1741 rasLogInternal ("Added object content:\n");
1742 rasCallLogObjectContent (h, &ctx, pinfo->objident, objhandle, objdata, cbobjdata, rasLogExternal);
[21916]1743
[21302]1744 rasLogInternal ("Existing object content:\n");
1745 rasCallLogObjectContent (h, &ctx, pinfo->objident, objhandle, pinfo->objdata, pinfo->cbobjdata, rasLogExternal);
[21916]1746
[21302]1747 if (rasCallCompareObjectContent (h, &ctx, objhandle, objdata, cbobjdata, pinfo->objdata, pinfo->cbobjdata) != 0)
1748 {
1749 rasLogInternal ("Objects are different\n");
1750 }
1751 }
1752 }
1753 else
1754 {
[21916]1755 pinfo = (RAS_OBJECT_INFO *)rasAlloc (sizeof (RAS_OBJECT_INFO) - sizeof (RAS_OBJECT_INFO::userdata)
1756 + h->cbuserdata
[21302]1757 + (objdata? cbobjdata: 0));
1758 if (pinfo)
1759 {
1760 rasInitObjectInfo (pinfo, h, objhandle, objdata, cbobjdata);
[21916]1761
[21302]1762 int rc = rasAddObjectInfo (pinfo, h, pinfo_next);
[21916]1763
[21302]1764 if (rc != NO_ERROR)
1765 {
[21916]1766 rasFree (pinfo);
[21302]1767 pinfo = NULL;
1768 }
1769 }
1770 }
1771
1772 EXIT_RAS ();
[21916]1773
[21302]1774 if (pinfo)
1775 {
1776 return pinfo->objident;
1777 }
[21916]1778
[21302]1779 return 0;
1780}
1781
1782void WIN32API RasRemoveObject (RAS_TRACK_HANDLE h, ULONG objhandle)
1783{
1784 ENTER_RAS (h);
[21916]1785
[21302]1786// rasLog ("Object to remove: handle = %8.8X\n", objhandle);
[21916]1787
[21302]1788 struct _RAS_OBJECT_INFO *pinfo = rasSearchObject (h, objhandle, NULL);
[21916]1789
[21302]1790// rasLog ("Objects pinfo = %8.8X\n", pinfo);
[21916]1791
[21302]1792 if (pinfo != NULL)
1793 {
1794 if (rasDecUseCount (pinfo) == 0)
1795 {
1796 rasRemoveObjectInfo (pinfo);
[21916]1797
[21302]1798 rasFree (pinfo);
1799 }
1800 }
[21916]1801
[21302]1802 EXIT_RAS ();
1803}
1804
[21916]1805
[21302]1806void WIN32API RasQueryObjectUserData (RAS_TRACK_HANDLE h, ULONG objident, void *pdata, ULONG cbdata, ULONG *pcbdataret)
1807{
1808 ENTER_RAS (h);
[21916]1809
[21302]1810 struct _RAS_OBJECT_INFO *pinfo = rasSearchObject2 (h, objident);
[21916]1811
[21302]1812 if (pinfo)
1813 {
1814 if (cbdata > pinfo->h->cbuserdata)
1815 {
1816 cbdata = pinfo->h->cbuserdata;
1817 }
[21916]1818
[21302]1819 memcpy (pdata, &pinfo->userdata, cbdata);
1820 }
1821 else
1822 {
1823 cbdata = 0;
1824 }
[21916]1825
[21302]1826 EXIT_RAS ();
[21916]1827
[21302]1828 if (pcbdataret)
1829 {
1830 *pcbdataret = cbdata;
1831 }
[21916]1832
[21302]1833 return;
1834}
1835
1836void WIN32API RasSetObjectUserData (RAS_TRACK_HANDLE h, ULONG objident, void *pdata, ULONG cbdata, ULONG *pcbdataret)
1837{
1838 ENTER_RAS (h);
[21916]1839
[21302]1840 struct _RAS_OBJECT_INFO *pinfo = rasSearchObject2 (h, objident);
[21916]1841
[21302]1842 if (pinfo)
1843 {
1844 if (cbdata > pinfo->h->cbuserdata)
1845 {
1846 cbdata = pinfo->h->cbuserdata;
1847 }
[21916]1848
[21302]1849 memcpy (&pinfo->userdata, pdata, cbdata);
1850 }
1851 else
1852 {
1853 cbdata = 0;
1854 }
[21916]1855
[21302]1856 EXIT_RAS ();
[21916]1857
[21302]1858 if (pcbdataret)
1859 {
1860 *pcbdataret = cbdata;
1861 }
[21916]1862
[21302]1863 return;
1864}
1865
1866
[21916]1867void WIN32API_VA RasLog (const char *fmt, ...)
[21302]1868{
1869 ENTER_RAS (NO_HANDLE);
[21916]1870
[21302]1871 va_list args;
1872
1873 va_start (args, fmt);
[21916]1874
[21302]1875 rasLogInternalV (NULL, fmt, args);
[21916]1876
[21302]1877 va_end (args);
[21916]1878
[21302]1879 EXIT_RAS ();
1880}
1881
[21916]1882void WIN32API_VA RasLogNoEOL (const char *fmt, ...)
[21302]1883{
1884 va_list args;
[21916]1885
[21302]1886 ENTER_RAS (NO_HANDLE);
[21916]1887
[21302]1888 va_start (args, fmt);
[21916]1889
[21302]1890 ULONG noeolstate = rasdata.fNoEOL;
1891
1892 rasdata.fNoEOL = 1;
[21916]1893
[21302]1894 rasLogInternalV (NULL, fmt, args);
[21916]1895
[21302]1896 rasdata.fNoEOL = noeolstate;
[21916]1897
[21302]1898 va_end (args);
[21916]1899
[21302]1900 EXIT_RAS ();
1901}
1902
1903void WIN32API RasLogMsg (ULONG msg, ULONG parm1, ULONG parm2)
1904{
1905 ENTER_RAS (NO_HANDLE);
[21916]1906
[21302]1907 EXIT_RAS ();
1908}
[21916]1909
[21302]1910void WIN32API RasLogObjects (RAS_TRACK_HANDLE h, ULONG flags)
1911{
1912 ENTER_RAS (h);
[21916]1913
[21302]1914 rasLogInternal ("[%s] objects", h->objname);
[21916]1915
[21302]1916 if (h->fMemory)
1917 {
1918 if (h->cAllocs)
1919 {
1920 // RasTrackMem APIs were used
1921 rasLogInternal (" allocations = %d, frees = %d", h->cAllocs, h->cFrees);
1922 rasLogInternal (" allocated %d bytes", h->cbTotalAllocated);
1923 }
1924 }
[21916]1925
[21302]1926 RAS_OBJECT_INFO *iter = h->objfirst;
[21916]1927
[21302]1928 int count = 0;
1929 ULONG cb = 0; // count total memory allocated if fMemory is set
[21916]1930
[21302]1931 while (iter)
1932 {
1933 if (h->fMemory)
1934 {
1935 cb += iter->cbobjdata;
1936 }
[21916]1937
[21302]1938 if (flags & RAS_FLAG_LOG_OBJECTS)
1939 {
1940 if (h->fMemory)
1941 {
1942 rasLogInternal (" address = %8.8X size = %d", iter->objhandle, iter->cbobjdata);
1943 }
1944 else
1945 {
1946 rasLogInternal (" handle = %8.8X\n", iter->objhandle);
[21916]1947
[21302]1948 if (h->fLogObjectContent)
1949 {
1950 rasCallLogObjectContent (h, &ctx, iter->objident, iter->objhandle, iter->objdata, iter->cbobjdata, rasLogExternal);
1951 }
1952 }
1953 }
[21916]1954
[21302]1955 count++;
[21916]1956
[21302]1957 iter = iter->next;
1958 }
[21916]1959
[21302]1960 rasLogInternal ("%d [%s] objects", count, h->objname);
[21916]1961
[21302]1962 if (h->fMemory && count > 0)
1963 {
1964 rasLogInternal ("%d bytes allocated", cb);
1965 }
[21916]1966
[21302]1967 EXIT_RAS ();
[21916]1968
[21302]1969 return;
1970}
1971
1972void WIN32API RasCountObjects (RAS_TRACK_HANDLE h, ULONG *pcount, ULONG *pallocated)
1973{
1974 ENTER_RAS (h);
[21916]1975
[21302]1976 RAS_OBJECT_INFO *iter = h->objfirst;
[21916]1977
[21302]1978 int count = 0;
1979 ULONG cb = 0; // count total memory allocated if fMemory is set
[21916]1980
[21302]1981 while (iter)
1982 {
1983 if (h->fMemory)
1984 {
1985 cb += iter->cbobjdata;
1986 }
[21916]1987
[21302]1988 count++;
[21916]1989
[21302]1990 iter = iter->next;
1991 }
[21916]1992
[21302]1993 if (h->fMemory)
1994 {
1995 if (pallocated)
1996 {
1997 *pallocated = cb + h->cbTotalAllocated;
1998 }
1999 }
[21916]2000
[21302]2001 if (pcount)
2002 {
2003 *pcount = count;
2004 }
[21916]2005
[21302]2006 EXIT_RAS ();
[21916]2007
[21302]2008 return;
2009}
2010
[21916]2011void WIN32API_VA RasLog2 (RAS_LOG_CHANNEL_H hchannel, char *fmt, ...)
[21302]2012{
2013 ENTER_RAS (NO_HANDLE);
[21916]2014
[21302]2015 va_list args;
2016
2017 va_start (args, fmt);
[21916]2018
[21302]2019 rasLogInternalV (hchannel, fmt, args);
[21916]2020
[21302]2021 va_end (args);
[21916]2022
[21302]2023 EXIT_RAS ();
2024}
2025
[21916]2026void WIN32API_VA RasLogNoEOL2 (RAS_LOG_CHANNEL_H hchannel, char *fmt, ...)
[21302]2027{
2028 va_list args;
[21916]2029
[21302]2030 ENTER_RAS (NO_HANDLE);
[21916]2031
[21302]2032 va_start (args, fmt);
[21916]2033
[21302]2034 ULONG noeolstate = rasdata.fNoEOL;
2035
2036 rasdata.fNoEOL = 1;
[21916]2037
[21302]2038 rasLogInternalV (hchannel, fmt, args);
[21916]2039
[21302]2040 rasdata.fNoEOL = noeolstate;
[21916]2041
[21302]2042 va_end (args);
[21916]2043
[21302]2044 EXIT_RAS ();
2045}
2046
2047void WIN32API RasLogMsg2 (RAS_LOG_CHANNEL_H hchannel, ULONG msg, ULONG parm1, ULONG parm2)
2048{
2049 ENTER_RAS (NO_HANDLE);
[21916]2050
[21302]2051 EXIT_RAS ();
2052}
2053
2054void WIN32API RasEnterSerialize (void)
2055{
2056 ENTER_RAS_NO_RESTORE ();
2057}
2058
2059void WIN32API RasExitSerialize (void)
2060{
2061 EXIT_RAS_NO_RESTORE ();
2062}
2063
2064int WIN32API RasOpenLogChannel (RAS_LOG_CHANNEL_H *phchannel, const char *env_loghandler,
2065 const char *filename)
2066{
2067 ENTER_RAS_RET (NO_HANDLE, ERROR_GEN_FAILURE);
[21916]2068
[21302]2069 int rc = NO_ERROR;
[21916]2070
[21302]2071 RasLogChannel *prlc = (RasLogChannel *)rasAlloc (sizeof (RasLogChannel));
[21916]2072
[21302]2073 if (!prlc)
2074 {
2075 rc = ERROR_NOT_ENOUGH_MEMORY;
2076 }
2077 else
2078 {
2079 rc = rasOpenLogChannel (env_loghandler, prlc, filename);
[21916]2080
[21302]2081 if (rc != NO_ERROR)
2082 {
2083 rasFree (prlc);
2084 }
2085 else
2086 {
2087 *phchannel = (RAS_LOG_CHANNEL_H)prlc;
2088 }
2089 }
[21916]2090
[21302]2091 EXIT_RAS ();
[21916]2092
[21302]2093 return rc;
2094}
[21916]2095
[21302]2096void WIN32API RasWriteLogChannel (RAS_LOG_CHANNEL_H hchannel, const char *msg, ULONG length)
2097{
2098 ENTER_RAS (NO_HANDLE);
[21916]2099
[21302]2100 if (length > 0)
2101 {
2102 RasLogChannel *prlc = (RasLogChannel *)hchannel;
[21916]2103
[21302]2104 prlc->pfnWriteLog (prlc->hlogfile, (char *)msg, length);
2105 }
[21916]2106
[21302]2107 EXIT_RAS ();
2108}
[21916]2109
[21302]2110void WIN32API RasCloseLogChannel (RAS_LOG_CHANNEL_H hchannel)
2111{
2112 ENTER_RAS (NO_HANDLE);
[21916]2113
[21302]2114 RasLogChannel *prlc = (RasLogChannel *)hchannel;
[21916]2115
[21302]2116 rasCloseLogChannel (prlc);
[21916]2117
[21302]2118 rasFree (prlc);
[21916]2119
[21302]2120 EXIT_RAS ();
2121}
2122
[21916]2123
[21302]2124void WIN32API RasEntry (ULONG ulEvent, void *p, ULONG cb)
2125{
2126 ENTER_RAS (NO_HANDLE);
[21916]2127
[21302]2128 if (rasdata.pet.RasEntry)
2129 {
2130 rasdata.pet.RasEntry (ulEvent, p, cb);
2131 }
[21916]2132
[21302]2133 EXIT_RAS ();
2134}
2135
2136void WIN32API RasSaveContext(RASCONTEXT *pcontext)
2137{
2138 rasSaveContext ((RASCONTEXT_I *)pcontext);
2139}
2140
2141void WIN32API RasRestoreContext(RASCONTEXT *pcontext)
2142{
2143 rasRestoreContext ((RASCONTEXT_I *)pcontext);
2144}
2145
2146FARPROC WIN32API RasSetProcAddr (ULONG hModule, LPCSTR lpszProc, FARPROC pfnNewProc)
2147{
2148 return ODIN_SetProcAddress(hModule, lpszProc, pfnNewProc);
2149}
2150
2151HMODULE WIN32API GetModuleHandleA(LPCSTR);
2152
2153ULONG WIN32API RasGetModuleHandle (LPCTSTR lpszModule)
2154{
2155 return GetModuleHandleA (lpszModule);
2156}
2157
2158void WIN32API RasTrackMemAlloc (RAS_TRACK_HANDLE h, ULONG size)
2159{
2160 ENTER_RAS (h);
[21916]2161
[21302]2162 if (h->fMemory && size > 0)
2163 {
2164 h->cAllocs++;
2165 h->cbTotalAllocated += size;
2166 }
[21916]2167
[21302]2168 EXIT_RAS ();
2169}
[21916]2170
[21302]2171void WIN32API RasTrackMemRealloc (RAS_TRACK_HANDLE h, ULONG oldsize, ULONG newsize)
2172{
2173 ENTER_RAS (h);
[21916]2174
[21302]2175 if (h->fMemory)
2176 {
2177 h->cbTotalAllocated += newsize - oldsize;
2178 if (newsize == 0)
2179 {
2180 rasLog ("WARNING: RasTrackMemRealloc: newsize = 0");
2181 }
2182 }
[21916]2183
[21302]2184 EXIT_RAS ();
2185}
[21916]2186
[21302]2187void WIN32API RasTrackMemFree (RAS_TRACK_HANDLE h, ULONG size)
2188{
2189 ENTER_RAS (h);
[21916]2190
[21302]2191 if (h->fMemory && size > 0)
2192 {
2193 h->cFrees++;
2194 h->cbTotalAllocated -= size;
2195 }
[21916]2196
[21302]2197 EXIT_RAS ();
2198}
[21916]2199
2200} // extern "C"
2201
Note: See TracBrowser for help on using the repository browser.