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

Last change on this file since 21302 was 21302, checked in by ydario, 16 years ago

Kernel32 updates.

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