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

Last change on this file since 21342 was 21342, checked in by abwillis, 16 years ago

VAC365 build updates. dsound update seems to help VAC308 some here too.

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