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

Last change on this file since 21916 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
Line 
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>
9#include <process.h>
10
11#include <custombuild.h>
12#include <odincrt.h>
13#ifdef __GNUC__
14#include <float.h>
15#else
16#include <libc/float.h>
17#endif
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:
25 *
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.
36 * External stuff that is used:
37 * - from Odin: asm helpers from interlock.asm
38 * - from libc: uheap functions
39 *
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
55typedef struct _RAS_OBJECT_INFO
56{
57 struct _RAS_OBJECT_INFO *next;
58 struct _RAS_OBJECT_INFO *prev;
59
60 RAS_TRACK_HANDLE h;
61
62 ULONG objident;
63 ULONG usecount;
64
65 ULONG objhandle;
66
67 void *objdata;
68 ULONG cbobjdata;
69
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;
80
81 char objname[80];
82
83 ULONG cbuserdata;
84
85 ULONG fLogObjectContent: 1;
86 ULONG fMemory: 1;
87 ULONG fLogAtExit: 1;
88 ULONG fLogObjectsAtExit: 1;
89
90 FNLOC *pfnLogObjectContent;
91 FNCOC *pfnCompareObjectContent;
92
93 /* Used when fMemory = 1 for RasTrackAlloc, Realloc and Free calls */
94 ULONG cAllocs;
95 ULONG cFrees;
96 ULONG cbTotalAllocated;
97
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
126
127 HMODULE hmod;
128} RasLogChannel;
129
130typedef struct _RAS_DATA
131{
132 HMODULE hmod; // handle of this dll
133
134 RasLogChannel rlc;
135
136 Heap_t rasheap;
137 void *pHeapMem;
138 ULONG ulRefCount;
139 ULONG flAllocMem;
140
141 HMODULE hmodPlugin;
142
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
170extern "C" {
171
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);
190
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;
197
198 rc = DosCreateEventSem (NULL, &crit->hevLock, DC_SEM_SHARED, 0);
199
200 if (rc != NO_ERROR)
201 {
202 crit->hevLock = 0;
203 }
204
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;
216
217 ULONG threadid = rasGetCurrentThreadId ();
218
219 // We want to acquire the section, count the entering
220 DosInterlockedIncrement (&crit->LockCount);
221
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 }
237
238 rc = DosWaitEventSem (crit->hevLock, ulTimeout);
239
240 if (rc != NO_ERROR)
241 {
242 // We fail, deregister itself
243 DosInterlockedDecrement (&crit->LockCount);
244 return rc;
245 }
246 }
247
248 // the section was successfully aquired
249 crit->RecursionCount = 1;
250
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);
265
266 return NO_ERROR;
267 }
268
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 }
279
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{
296 static const char *digits = "0123456789ABCDEF";
297
298 unsigned long tmp = number;
299 char *s = string;
300 int len = 0;
301 int l = 0;
302 int i;
303
304 if (n <= 0)
305 {
306 return;
307 }
308
309 if (tmp == 0)
310 {
311 s[l++] = digits[0];
312 }
313
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 }
328
329 s = string;
330
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 }
347
348 if (number < 0)
349 {
350 *string++ = '-';
351 number = -number;
352 n--;
353 }
354
355 ulong2string (number, string, n, base);
356}
357
358int string2ulong (const char *string, char **pstring2, unsigned long *pvalue, int base)
359{
360 unsigned long value = 0;
361 int sign = 1;
362
363 const char *p = string;
364
365 if (p[0] == '-')
366 {
367 sign = -1;
368 p++;
369 }
370
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 }
388
389 while (*p)
390 {
391 int digit = 0;
392
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 }
409
410 if (digit >= base)
411 {
412 break;
413 }
414
415 value = value*base + digit;
416
417 p++;
418 }
419
420 if (pstring2)
421 {
422 *pstring2 = (char *)p;
423 }
424
425 *pvalue = sign*value;
426
427 return 1;
428}
429
430#ifndef __GNUC__
431
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;
437
438 if (n <= 0)
439 {
440 return 0;
441 }
442
443 n--;
444
445 while (*s && count < n)
446 {
447 char tmpstr[16];
448
449 char *str = NULL;
450
451 int width = 0;
452 int precision = 0;
453
454 if (*s == '%')
455 {
456 s++;
457
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 }
473
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);
491
492 ulong2string (num, tmpstr, sizeof (tmpstr), 16);
493
494 str = &tmpstr[0];
495 s++;
496 width = 8;
497 precision = 8;
498 }
499 else
500 {
501 if (*s == 'l')
502 {
503 s++;
504 }
505
506 if (*s == 'd' || *s == 'i')
507 {
508 int num = va_arg(args, int);
509
510 long2string (num, tmpstr, sizeof (tmpstr), 10);
511
512 str = &tmpstr[0];
513 s++;
514 }
515 else if (*s == 'u')
516 {
517 int num = va_arg(args, int);
518
519 ulong2string (num, tmpstr, sizeof (tmpstr), 10);
520
521 str = &tmpstr[0];
522 s++;
523 }
524 else if (*s == 'x' || *s == 'X')
525 {
526 int num = va_arg(args, int);
527
528 ulong2string (num, tmpstr, sizeof (tmpstr), 16);
529
530 str = &tmpstr[0];
531 s++;
532 }
533 }
534 }
535
536 if (str != NULL)
537 {
538 int i;
539 char numstr[16];
540 int len = strlen (str);
541 int leftalign = 0;
542
543 if (width < 0)
544 {
545 width = -width;
546 leftalign = 1;
547 }
548
549 if (precision)
550 {
551 i = 0;
552 while (precision > len)
553 {
554 numstr[i++] = '0';
555 precision--;
556 }
557
558 memcpy (&numstr[i], str, len);
559
560 str = &numstr[0];
561 len += i;
562 }
563
564 if (len < width && !leftalign)
565 {
566 while (len < width && count < n)
567 {
568 *d++ = ' ';
569 width--;
570 count++;
571 }
572
573 if (count >= n)
574 {
575 break;
576 }
577 }
578
579 i = 0;
580 while (i < len && count < n)
581 {
582 *d++ = str[i++];
583 count++;
584 }
585
586 if (count >= n)
587 {
588 break;
589 }
590
591 if (len < width && leftalign)
592 {
593 while (len < width && count < n)
594 {
595 *d++ = ' ';
596 width--;
597 count++;
598 }
599
600 if (count >= n)
601 {
602 break;
603 }
604 }
605 }
606 else
607 {
608 *d++ = *s++;
609 count++;
610 }
611 }
612
613 *d = '\0';
614
615 return count + 1;
616}
617
618#endif // ifndef __GNUC__
619
620#ifdef __GNUC__
621int WIN32API_VA ras_snprintf (char *buf, int n, const char *fmt, ...)
622#else
623int WIN32API snprintf (char *buf, int n, const char *fmt, ...)
624#endif
625{
626 va_list args;
627
628 int rc = 0;
629
630 va_start (args, fmt);
631
632 rc = vsnprintf (buf, n, fmt, args);
633
634 va_end (args);
635
636 return rc;
637}
638
639int WIN32API rasOpenLogFile (ULONG *ph, const char *logfilename)
640{
641 ULONG ulAction = 0;
642
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);
647
648 if (rc == ERROR_TOO_MANY_OPEN_FILES)
649 {
650 LONG lReqCount = 10l;
651 ULONG ulCurMaxFH = 0ul;
652
653 DosSetRelMaxFH (&lReqCount, &ulCurMaxFH);
654
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 }
660
661 if (rc != NO_ERROR)
662 {
663 *ph = -1;
664 }
665
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;
677
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 }
688
689 if (prlc->hmod)
690 {
691 DosFreeModule (prlc->hmod);
692 prlc->hmod = NULLHANDLE;
693 }
694
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;
704
705 const char *env = NULL;
706
707 DosScanEnv (env_loghandler, &env);
708
709 HMODULE hmod = NULLHANDLE;
710
711 PFN popenlogfile = NULL;
712 PFN pcloselogfile = NULL;
713 PFN pwritelog = NULL;
714
715 if (env)
716 {
717 rc = DosLoadModule (NULL, 0, env, &hmod);
718
719 if (rc == NO_ERROR)
720 {
721 rc = DosQueryProcAddr (hmod, 0, "WIN32RAS_OPENLOGFILE", &popenlogfile);
722 }
723
724 if (rc == NO_ERROR)
725 {
726 rc = DosQueryProcAddr (hmod, 0, "WIN32RAS_CLOSELOGFILE", &pcloselogfile);
727 }
728
729 if (rc == NO_ERROR)
730 {
731 rc = DosQueryProcAddr (hmod, 0, "WIN32RAS_WRITELOG", &pwritelog);
732 }
733
734 if (rc != NO_ERROR && hmod)
735 {
736 DosFreeModule (hmod);
737 hmod = NULLHANDLE;
738 }
739 }
740
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;
756
757 rc = NO_ERROR;
758 }
759
760 rc = prlc->pfnOpenLogFile (&prlc->hlogfile, filename);
761
762 if (rc != NO_ERROR)
763 {
764 prlc->hlogfile = -1;
765 rasCloseLogChannel (prlc);
766 }
767
768 return rc;
769}
770
771int rasInitializeLog (void)
772{
773 int rc = NO_ERROR;
774
775 const char *filename = "win32ras.log";
776
777 const char *env = NULL;
778
779 DosScanEnv ("WIN32RAS_LOG_FILENAME", &env);
780
781 if (env)
782 {
783 filename = env;
784 }
785
786 char uniqueLogFileName[260];
787
788 snprintf (uniqueLogFileName, sizeof(uniqueLogFileName),
789 "%s.%d", filename, getpid());
790
791 if (rasdata.rlc.hlogfile == -1)
792 {
793 rc = rasOpenLogChannel ("WIN32RAS_LOGHANDLER", &rasdata.rlc, uniqueLogFileName);
794 }
795
796 return rc;
797}
798
799void rasUninitializeLog (void)
800{
801 rasCloseLogChannel (&rasdata.rlc);
802}
803
804void rasLogInternalV (RAS_LOG_CHANNEL_H hchannel, const char *fmt, va_list args)
805{
806 static char szOutMsg[4096];
807
808 ULONG ulHdrLen = snprintf (szOutMsg, sizeof (szOutMsg), "%s", "");
809
810 ulHdrLen -= 1;
811
812 ULONG ulMsgLen = vsnprintf (&szOutMsg[ulHdrLen], sizeof (szOutMsg) - ulHdrLen, fmt, args);
813
814 ulMsgLen -= 1;
815
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 }
827
828 RasLogChannel *prlc = hchannel? (RasLogChannel *)hchannel: &rasdata.rlc;
829
830 prlc->pfnWriteLog (prlc->hlogfile, szOutMsg, ulMsgLen + ulHdrLen);
831 }
832}
833
834void rasLog (const char *fmt, ...)
835{
836 va_list args;
837
838 va_start (args, fmt);
839
840 rasLogInternalV (NULL, fmt, args);
841
842 va_end (args);
843}
844
845void rasLogInternal (const char *fmt, ...)
846{
847 va_list args;
848
849 va_start (args, fmt);
850
851 rasLogInternalV (NULL, fmt, args);
852
853 va_end (args);
854}
855
856void WIN32API_VA rasLogExternal (const char *fmt, ...)
857{
858 va_list args;
859
860 USHORT sel = RestoreOS2FS();
861
862 va_start (args, fmt);
863
864 rasLogInternalV (NULL, fmt, args);
865
866 va_end (args);
867
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;
893
894 rc = DosAllocSharedMem (&p, NULL, *size, rasdata.flAllocMem | OBJ_GETTABLE);
895
896 if (rc != NO_ERROR)
897 {
898 rasLog ("RAS heap: getmore_fn: DosAllocSharedMem failed, rc = %d\n", rc);
899 }
900
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;
923
924 if (rascfg.fUseHighMem)
925 {
926 ULONG ulSysinfo = 0;
927
928 rc = DosQuerySysInfo (QSV_VIRTUALADDRESSLIMIT, QSV_VIRTUALADDRESSLIMIT, &ulSysinfo, sizeof (ulSysinfo));
929
930 if (rc == NO_ERROR && ulSysinfo > 512) // VirtualAddresslimit is in MB
931 {
932 rasdata.flAllocMem |= PAG_ANY;
933
934 rasLog ("RAS heap initialization: will use high memory\n");
935 }
936 }
937
938 rc = DosAllocSharedMem (&rasdata.pHeapMem, NULL, rascfg.ulInitHeapSize,
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 }
945
946 rasdata.rasheap = _ucreate (rasdata.pHeapMem, rascfg.ulInitHeapSize,
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");
953
954 DosFreeMem (rasdata.pHeapMem);
955 rasdata.pHeapMem = NULL;
956
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);
966
967 if (rc != NO_ERROR)
968 {
969 rasLog ("RAS heap initialization: DosGetSharedMem failed %d\n", rc);
970
971 return rc;
972 }
973
974 if (_uopen (rasdata.rasheap) != 0)
975 {
976 rasLog ("RAS heap initialization: _uopen failed\n");
977
978 DosFreeMem (rasdata.pHeapMem);
979
980 return ERROR_NOT_ENOUGH_MEMORY;
981 }
982 }
983
984 rasdata.ulRefCount++;
985
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 }
997
998 if (useflag == _USEDENTRY)
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);
1018
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);
1034
1035 _udestroy (rasdata.rasheap, _FORCE);
1036 rasdata.rasheap = NULL;
1037 }
1038
1039 if (rasdata.pHeapMem)
1040 {
1041 DosFreeMem (rasdata.pHeapMem);
1042 rasdata.pHeapMem = NULL;
1043 }
1044 }
1045 else
1046 {
1047 _uclose (rasdata.rasheap);
1048 }
1049}
1050
1051void *rasAlloc (ULONG size)
1052{
1053 void *p = _umalloc(rasdata.rasheap, size);
1054
1055 if (p)
1056 {
1057 memset (p, 0, size);
1058 }
1059 else
1060 {
1061 rasLog ("RAS heap: allocation failed, %d bytes\n", size);
1062 }
1063
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;
1077
1078 while (iter)
1079 {
1080 if (iter == h)
1081 {
1082 break;
1083 }
1084
1085 iter = iter->next;
1086 }
1087
1088 return iter;
1089}
1090
1091ULONG rasGenObjIdent (void)
1092{
1093 static ULONG objident = 0;
1094
1095 objident++;
1096
1097 if (objident == 0)
1098 {
1099 objident++;
1100 }
1101
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 }
1117
1118 return NO_ERROR;
1119}
1120
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 }
1132
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;
1148
1149 pinfo->h = h;
1150
1151 pinfo->usecount = 1;
1152
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 }
1163
1164 pinfo->cbobjdata = cbobjdata;
1165}
1166
1167struct _RAS_OBJECT_INFO *rasSearchObject2 (RAS_TRACK_HANDLE h, ULONG objident)
1168{
1169 if (!h)
1170 {
1171 return NULL;
1172 }
1173
1174 RAS_OBJECT_INFO *iter = h->objfirst;
1175
1176 while (iter)
1177 {
1178 if (iter->objident == objident)
1179 {
1180 break;
1181 }
1182 iter = iter->next;
1183 }
1184
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{
1198 if (!h)
1199 {
1200 return NULL;
1201 }
1202
1203 RAS_OBJECT_INFO *iter = h->objfirst;
1204
1205 while (iter)
1206 {
1207 if (iter->objhandle == objhandle)
1208 {
1209 break;
1210 }
1211
1212 iter = iter->next;
1213 }
1214
1215 if (iter && ppinfo_next)
1216 {
1217 *ppinfo_next = iter->next;
1218 }
1219
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--;
1231
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];
1240
1241 if (!objdata)
1242 {
1243 return NO_ERROR;
1244 }
1245
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 }
1255
1256 snprintf (p, sizeof(buf) - (p - &buf[0]), "%8.8x:", i / 16);
1257 p += strlen (p);
1258 }
1259
1260 snprintf (p, sizeof(buf) - (p - &buf[0]), " %2.2x", ((char *)objdata)[i]);
1261 p += strlen (p);
1262 }
1263
1264 pRasLog ("%s\n", buf);
1265
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 }
1275
1276 if (objdata1 == NULL || objdata2 == NULL)
1277 {
1278 // can't compare, assume they are not equal
1279 return 1;
1280 }
1281
1282 return memcmp (objdata1, objdata2, cbobjdata1);
1283}
1284
1285ULONG rasCallLogObjectContent (RAS_TRACK_HANDLE h, RASCONTEXT_I *pctx,
1286 ULONG objident, ULONG objhandle,
1287 void *objdata, ULONG cbobjdata, FNRASLOG_EXTERNAL *rasLogExternal)
1288{
1289 rasRestoreContext (pctx);
1290
1291 ULONG rc = h->pfnLogObjectContent (objident, objhandle, objdata, cbobjdata, rasLogExternal);
1292
1293 rasSaveContext (pctx);
1294
1295 return rc;
1296}
1297
1298ULONG WIN32API rasCallCompareObjectContent (RAS_TRACK_HANDLE h, RASCONTEXT_I *pctx,
1299 ULONG objhandle, void *objdata1, ULONG cbobjdata1, void *objdata2, ULONG cbobjdata2)
1300{
1301 rasRestoreContext (pctx);
1302
1303 ULONG rc = h->pfnCompareObjectContent (objhandle, objdata1, cbobjdata1, objdata2, cbobjdata2);
1304
1305 rasSaveContext (pctx);
1306
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;
1318
1319 DosScanEnv (name, &env);
1320
1321 if (env)
1322 {
1323 ULONG ul = 0;
1324 char *e = NULL;
1325
1326 string2ulong (env, &e, &ul, 10);
1327
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;
1341
1342 if (!rasdata.hmodPlugin)
1343 {
1344 rasdata.ret.cb = sizeof (RasEntryTable);
1345
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;
1360#ifdef __GNUC__
1361 rasdata.ret.snprintf = ras_snprintf;
1362#else
1363 rasdata.ret.snprintf = snprintf;
1364#endif
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;
1374
1375 rasdata.pet.cb = sizeof (RasPluginEntryTable);
1376
1377 rasdata.pet.RasEntry = _RasEntry;
1378
1379 const char *env = NULL;
1380
1381 DosScanEnv ("WIN32RAS_PLUGIN", &env);
1382
1383 if (env)
1384 {
1385 HMODULE hmod = NULLHANDLE;
1386 FNPI *pfnPluginInit = NULL;
1387
1388 rc = DosLoadModule (NULL, 0, env, &hmod);
1389
1390 if (rc == NO_ERROR)
1391 {
1392 rc = DosQueryProcAddr (hmod, 0, "WIN32RAS_PLUGIN_INIT", (PFN *)&pfnPluginInit);
1393 }
1394
1395 if (rc != NO_ERROR)
1396 {
1397 rasLogInternal ("Could not load RAS plugin %s rc = %d", env, rc);
1398 }
1399
1400 if (rc != NO_ERROR && hmod)
1401 {
1402 DosFreeModule (hmod);
1403 }
1404 else
1405 {
1406 rasdata.hmodPlugin = hmod;
1407
1408 pfnPluginInit (rasdata.hmod, &rasdata.ret, &rasdata.pet);
1409 }
1410 }
1411 }
1412
1413 return rc;
1414}
1415
1416int rasUninitializePlugin (void)
1417{
1418 int rc = NO_ERROR;
1419
1420 if (rasdata.hmodPlugin)
1421 {
1422 HMODULE hmod = rasdata.hmodPlugin;
1423 FNPE *pfnPluginExit = NULL;
1424
1425 rc = DosQueryProcAddr (hmod, 0, "WIN32RAS_PLUGIN_EXIT", (PFN *)&pfnPluginExit);
1426
1427 if (rc == NO_ERROR)
1428 {
1429 pfnPluginExit (rasdata.hmod);
1430 }
1431
1432 DosFreeModule (hmod);
1433 }
1434
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;
1484
1485 if (!rasInitialized)
1486 {
1487 rasInitialized = 1;
1488
1489 memset (&rascfg, 0, sizeof (rascfg));
1490
1491 rascfg.ulTimeout = 60000; // default 1 minute
1492 rasQueryEnvUlong ("WIN32RAS_TIMEOUT", &rascfg.ulTimeout, 1, 3600, 1000);
1493
1494 rascfg.ulInitHeapSize = 128*1024;
1495 rasQueryEnvUlong ("WIN32RAS_INITHEAPSIZE", &rascfg.ulInitHeapSize, 64, 16*1024, 1024);
1496
1497 ULONG ul = 0;
1498 rasQueryEnvUlong ("WIN32RAS_DUMPHEAPOBJECTS", &ul, 0, 1, 1);
1499 rascfg.fDumpHeapObjects = ul;
1500
1501 ul = 1;
1502 rasQueryEnvUlong ("WIN32RAS_USEHIGHMEM", &ul, 0, 1, 1);
1503 rascfg.fUseHighMem = ul;
1504
1505 ul = 0;
1506 rasQueryEnvUlong ("WIN32RAS_ENABLE", &ul, 0, 1, 1);
1507 rascfg.fRasEnable = ul;
1508
1509 ul = 0;
1510 rasQueryEnvUlong ("WIN32RAS_BREAKPOINT", &ul, 0, 1, 1);
1511 rascfg.fRasBreakPoint = ul;
1512
1513 memset (&rasdata, 0, sizeof (rasdata));
1514 rasdata.rlc.hlogfile = -1;
1515 rasdata.hmod = hmod;
1516
1517 rc = NO_ERROR;
1518 }
1519
1520 if (!rascfg.fRasEnable)
1521 {
1522 return rc;
1523 }
1524
1525 if (rascfg.fRasBreakPoint)
1526 {
1527 _interrupt(3);
1528 }
1529
1530 rc = rasInitializeLog ();
1531
1532 if (rc == NO_ERROR)
1533 {
1534 rc = rasInitializeCriticalSection (&csras);
1535 }
1536
1537 if (rc == NO_ERROR)
1538 {
1539 rc = rasInitializeHeap ();
1540 }
1541
1542 if (rc == NO_ERROR)
1543 {
1544 rc = rasInitializePlugin ();
1545 }
1546
1547 return rc;
1548}
1549
1550void WIN32API RasUninitialize (void)
1551{
1552 ENTER_RAS(NO_HANDLE);
1553
1554 /* Deregister all objects */
1555 while (rasdata.firsttrack)
1556 {
1557 RAS_TRACK_HANDLE iter = rasdata.firsttrack;
1558
1559 if (iter->fLogAtExit)
1560 {
1561 RasLogObjects (iter, iter->fLogObjectsAtExit? RAS_FLAG_LOG_OBJECTS: 0);
1562 }
1563
1564 RasDeregisterObjectTracking (iter);
1565
1566 rasFree (iter);
1567 }
1568
1569 rasUninitializePlugin ();
1570
1571 rasUninitializeHeap ();
1572
1573 EXIT_RAS();
1574
1575 rasUninitializeCriticalSection (&csras);
1576
1577 rasUninitializeLog ();
1578}
1579
1580RAS_TRACK_HANDLE WIN32API RasGetTrackHandle (const char *objname)
1581{
1582 ENTER_RAS_RET(NO_HANDLE, NULL);
1583
1584 RAS_TRACK_HANDLE iter = rasdata.firsttrack;
1585
1586 while (iter)
1587 {
1588 if (stricmp (objname, iter->objname) == 0)
1589 {
1590 break;
1591 }
1592
1593 iter = iter->next;
1594 }
1595
1596 EXIT_RAS();
1597
1598 return iter;
1599}
1600
1601void WIN32API RasRegisterObjectTracking (RAS_TRACK_HANDLE *ph, const char *objname,
1602 ULONG cbuserdata,
1603 ULONG flags,
1604 FNLOC *pfnLogObjectContent,
1605 FNCOC *pfnCompareObjectContent)
1606{
1607 ENTER_RAS(NO_HANDLE);
1608
1609 RAS_TRACK *prt = (RAS_TRACK *)rasAlloc (sizeof (RAS_TRACK));
1610
1611 if (prt)
1612 {
1613 strcpy (prt->objname, objname);
1614
1615 prt->cbuserdata = cbuserdata;
1616
1617 if (flags & RAS_TRACK_FLAG_LOGOBJECTCONTENT)
1618 {
1619 prt->fLogObjectContent = 1;
1620 }
1621
1622 if (flags & RAS_TRACK_FLAG_MEMORY)
1623 {
1624 prt->fMemory = 1;
1625 }
1626
1627 if (flags & RAS_TRACK_FLAG_LOG_AT_EXIT)
1628 {
1629 prt->fLogAtExit = 1;
1630 }
1631
1632 if (flags & RAS_TRACK_FLAG_LOG_OBJECTS_AT_EXIT)
1633 {
1634 prt->fLogObjectsAtExit = 1;
1635 }
1636
1637 if (pfnLogObjectContent)
1638 {
1639 prt->pfnLogObjectContent = pfnLogObjectContent;
1640 }
1641 else
1642 {
1643 prt->pfnLogObjectContent = rasLogObjectContent;
1644 }
1645
1646 if (pfnCompareObjectContent)
1647 {
1648 prt->pfnCompareObjectContent = pfnCompareObjectContent;
1649 }
1650 else
1651 {
1652 prt->pfnCompareObjectContent = pfnCompareObjectContent;
1653 }
1654
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 }
1666
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);
1678
1679 if (h)
1680 {
1681 /* Remove all objects */
1682 while (h->objfirst)
1683 {
1684 RAS_OBJECT_INFO *iter = h->objfirst;
1685
1686 rasRemoveObjectInfo (iter);
1687
1688 rasFree (iter);
1689 }
1690
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 }
1701
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 }
1712
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);
1721
1722 struct _RAS_OBJECT_INFO *pinfo_next = NULL;
1723
1724 struct _RAS_OBJECT_INFO *pinfo = rasSearchObject (h, objhandle, &pinfo_next);
1725
1726// rasLog ("Object added: handle = %8.8X\n", objhandle);
1727
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);
1736
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);
1743
1744 rasLogInternal ("Existing object content:\n");
1745 rasCallLogObjectContent (h, &ctx, pinfo->objident, objhandle, pinfo->objdata, pinfo->cbobjdata, rasLogExternal);
1746
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 {
1755 pinfo = (RAS_OBJECT_INFO *)rasAlloc (sizeof (RAS_OBJECT_INFO) - sizeof (RAS_OBJECT_INFO::userdata)
1756 + h->cbuserdata
1757 + (objdata? cbobjdata: 0));
1758 if (pinfo)
1759 {
1760 rasInitObjectInfo (pinfo, h, objhandle, objdata, cbobjdata);
1761
1762 int rc = rasAddObjectInfo (pinfo, h, pinfo_next);
1763
1764 if (rc != NO_ERROR)
1765 {
1766 rasFree (pinfo);
1767 pinfo = NULL;
1768 }
1769 }
1770 }
1771
1772 EXIT_RAS ();
1773
1774 if (pinfo)
1775 {
1776 return pinfo->objident;
1777 }
1778
1779 return 0;
1780}
1781
1782void WIN32API RasRemoveObject (RAS_TRACK_HANDLE h, ULONG objhandle)
1783{
1784 ENTER_RAS (h);
1785
1786// rasLog ("Object to remove: handle = %8.8X\n", objhandle);
1787
1788 struct _RAS_OBJECT_INFO *pinfo = rasSearchObject (h, objhandle, NULL);
1789
1790// rasLog ("Objects pinfo = %8.8X\n", pinfo);
1791
1792 if (pinfo != NULL)
1793 {
1794 if (rasDecUseCount (pinfo) == 0)
1795 {
1796 rasRemoveObjectInfo (pinfo);
1797
1798 rasFree (pinfo);
1799 }
1800 }
1801
1802 EXIT_RAS ();
1803}
1804
1805
1806void WIN32API RasQueryObjectUserData (RAS_TRACK_HANDLE h, ULONG objident, void *pdata, ULONG cbdata, ULONG *pcbdataret)
1807{
1808 ENTER_RAS (h);
1809
1810 struct _RAS_OBJECT_INFO *pinfo = rasSearchObject2 (h, objident);
1811
1812 if (pinfo)
1813 {
1814 if (cbdata > pinfo->h->cbuserdata)
1815 {
1816 cbdata = pinfo->h->cbuserdata;
1817 }
1818
1819 memcpy (pdata, &pinfo->userdata, cbdata);
1820 }
1821 else
1822 {
1823 cbdata = 0;
1824 }
1825
1826 EXIT_RAS ();
1827
1828 if (pcbdataret)
1829 {
1830 *pcbdataret = cbdata;
1831 }
1832
1833 return;
1834}
1835
1836void WIN32API RasSetObjectUserData (RAS_TRACK_HANDLE h, ULONG objident, void *pdata, ULONG cbdata, ULONG *pcbdataret)
1837{
1838 ENTER_RAS (h);
1839
1840 struct _RAS_OBJECT_INFO *pinfo = rasSearchObject2 (h, objident);
1841
1842 if (pinfo)
1843 {
1844 if (cbdata > pinfo->h->cbuserdata)
1845 {
1846 cbdata = pinfo->h->cbuserdata;
1847 }
1848
1849 memcpy (&pinfo->userdata, pdata, cbdata);
1850 }
1851 else
1852 {
1853 cbdata = 0;
1854 }
1855
1856 EXIT_RAS ();
1857
1858 if (pcbdataret)
1859 {
1860 *pcbdataret = cbdata;
1861 }
1862
1863 return;
1864}
1865
1866
1867void WIN32API_VA RasLog (const char *fmt, ...)
1868{
1869 ENTER_RAS (NO_HANDLE);
1870
1871 va_list args;
1872
1873 va_start (args, fmt);
1874
1875 rasLogInternalV (NULL, fmt, args);
1876
1877 va_end (args);
1878
1879 EXIT_RAS ();
1880}
1881
1882void WIN32API_VA RasLogNoEOL (const char *fmt, ...)
1883{
1884 va_list args;
1885
1886 ENTER_RAS (NO_HANDLE);
1887
1888 va_start (args, fmt);
1889
1890 ULONG noeolstate = rasdata.fNoEOL;
1891
1892 rasdata.fNoEOL = 1;
1893
1894 rasLogInternalV (NULL, fmt, args);
1895
1896 rasdata.fNoEOL = noeolstate;
1897
1898 va_end (args);
1899
1900 EXIT_RAS ();
1901}
1902
1903void WIN32API RasLogMsg (ULONG msg, ULONG parm1, ULONG parm2)
1904{
1905 ENTER_RAS (NO_HANDLE);
1906
1907 EXIT_RAS ();
1908}
1909
1910void WIN32API RasLogObjects (RAS_TRACK_HANDLE h, ULONG flags)
1911{
1912 ENTER_RAS (h);
1913
1914 rasLogInternal ("[%s] objects", h->objname);
1915
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 }
1925
1926 RAS_OBJECT_INFO *iter = h->objfirst;
1927
1928 int count = 0;
1929 ULONG cb = 0; // count total memory allocated if fMemory is set
1930
1931 while (iter)
1932 {
1933 if (h->fMemory)
1934 {
1935 cb += iter->cbobjdata;
1936 }
1937
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);
1947
1948 if (h->fLogObjectContent)
1949 {
1950 rasCallLogObjectContent (h, &ctx, iter->objident, iter->objhandle, iter->objdata, iter->cbobjdata, rasLogExternal);
1951 }
1952 }
1953 }
1954
1955 count++;
1956
1957 iter = iter->next;
1958 }
1959
1960 rasLogInternal ("%d [%s] objects", count, h->objname);
1961
1962 if (h->fMemory && count > 0)
1963 {
1964 rasLogInternal ("%d bytes allocated", cb);
1965 }
1966
1967 EXIT_RAS ();
1968
1969 return;
1970}
1971
1972void WIN32API RasCountObjects (RAS_TRACK_HANDLE h, ULONG *pcount, ULONG *pallocated)
1973{
1974 ENTER_RAS (h);
1975
1976 RAS_OBJECT_INFO *iter = h->objfirst;
1977
1978 int count = 0;
1979 ULONG cb = 0; // count total memory allocated if fMemory is set
1980
1981 while (iter)
1982 {
1983 if (h->fMemory)
1984 {
1985 cb += iter->cbobjdata;
1986 }
1987
1988 count++;
1989
1990 iter = iter->next;
1991 }
1992
1993 if (h->fMemory)
1994 {
1995 if (pallocated)
1996 {
1997 *pallocated = cb + h->cbTotalAllocated;
1998 }
1999 }
2000
2001 if (pcount)
2002 {
2003 *pcount = count;
2004 }
2005
2006 EXIT_RAS ();
2007
2008 return;
2009}
2010
2011void WIN32API_VA RasLog2 (RAS_LOG_CHANNEL_H hchannel, char *fmt, ...)
2012{
2013 ENTER_RAS (NO_HANDLE);
2014
2015 va_list args;
2016
2017 va_start (args, fmt);
2018
2019 rasLogInternalV (hchannel, fmt, args);
2020
2021 va_end (args);
2022
2023 EXIT_RAS ();
2024}
2025
2026void WIN32API_VA RasLogNoEOL2 (RAS_LOG_CHANNEL_H hchannel, char *fmt, ...)
2027{
2028 va_list args;
2029
2030 ENTER_RAS (NO_HANDLE);
2031
2032 va_start (args, fmt);
2033
2034 ULONG noeolstate = rasdata.fNoEOL;
2035
2036 rasdata.fNoEOL = 1;
2037
2038 rasLogInternalV (hchannel, fmt, args);
2039
2040 rasdata.fNoEOL = noeolstate;
2041
2042 va_end (args);
2043
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);
2050
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);
2068
2069 int rc = NO_ERROR;
2070
2071 RasLogChannel *prlc = (RasLogChannel *)rasAlloc (sizeof (RasLogChannel));
2072
2073 if (!prlc)
2074 {
2075 rc = ERROR_NOT_ENOUGH_MEMORY;
2076 }
2077 else
2078 {
2079 rc = rasOpenLogChannel (env_loghandler, prlc, filename);
2080
2081 if (rc != NO_ERROR)
2082 {
2083 rasFree (prlc);
2084 }
2085 else
2086 {
2087 *phchannel = (RAS_LOG_CHANNEL_H)prlc;
2088 }
2089 }
2090
2091 EXIT_RAS ();
2092
2093 return rc;
2094}
2095
2096void WIN32API RasWriteLogChannel (RAS_LOG_CHANNEL_H hchannel, const char *msg, ULONG length)
2097{
2098 ENTER_RAS (NO_HANDLE);
2099
2100 if (length > 0)
2101 {
2102 RasLogChannel *prlc = (RasLogChannel *)hchannel;
2103
2104 prlc->pfnWriteLog (prlc->hlogfile, (char *)msg, length);
2105 }
2106
2107 EXIT_RAS ();
2108}
2109
2110void WIN32API RasCloseLogChannel (RAS_LOG_CHANNEL_H hchannel)
2111{
2112 ENTER_RAS (NO_HANDLE);
2113
2114 RasLogChannel *prlc = (RasLogChannel *)hchannel;
2115
2116 rasCloseLogChannel (prlc);
2117
2118 rasFree (prlc);
2119
2120 EXIT_RAS ();
2121}
2122
2123
2124void WIN32API RasEntry (ULONG ulEvent, void *p, ULONG cb)
2125{
2126 ENTER_RAS (NO_HANDLE);
2127
2128 if (rasdata.pet.RasEntry)
2129 {
2130 rasdata.pet.RasEntry (ulEvent, p, cb);
2131 }
2132
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);
2161
2162 if (h->fMemory && size > 0)
2163 {
2164 h->cAllocs++;
2165 h->cbTotalAllocated += size;
2166 }
2167
2168 EXIT_RAS ();
2169}
2170
2171void WIN32API RasTrackMemRealloc (RAS_TRACK_HANDLE h, ULONG oldsize, ULONG newsize)
2172{
2173 ENTER_RAS (h);
2174
2175 if (h->fMemory)
2176 {
2177 h->cbTotalAllocated += newsize - oldsize;
2178 if (newsize == 0)
2179 {
2180 rasLog ("WARNING: RasTrackMemRealloc: newsize = 0");
2181 }
2182 }
2183
2184 EXIT_RAS ();
2185}
2186
2187void WIN32API RasTrackMemFree (RAS_TRACK_HANDLE h, ULONG size)
2188{
2189 ENTER_RAS (h);
2190
2191 if (h->fMemory && size > 0)
2192 {
2193 h->cFrees++;
2194 h->cbTotalAllocated -= size;
2195 }
2196
2197 EXIT_RAS ();
2198}
2199
2200} // extern "C"
2201
Note: See TracBrowser for help on using the repository browser.