2
* Copyright (c) 2005 Massachusetts Institute of Technology
4
* Permission is hereby granted, free of charge, to any person
5
* obtaining a copy of this software and associated documentation
6
* files (the "Software"), to deal in the Software without
7
* restriction, including without limitation the rights to use, copy,
8
* modify, merge, publish, distribute, sublicense, and/or sell copies
9
* of the Software, and to permit persons to whom the Software is
10
* furnished to do so, subject to the following conditions:
12
* The above copyright notice and this permission notice shall be
13
* included in all copies or substantial portions of the Software.
15
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
19
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
20
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
21
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
27
#include<kherrinternal.h>
31
CRITICAL_SECTION cs_error;
33
kherr_context * ctx_free_list = NULL;
34
kherr_context * ctx_root_list = NULL;
35
kherr_context * ctx_error_list = NULL;
36
kherr_event * evt_free_list = NULL;
38
kherr_handler_node * ctx_handlers = NULL;
39
khm_size n_ctx_handlers;
40
khm_size nc_ctx_handlers;
42
kherr_serial ctx_serial = 0;
48
kherr_debug_printf(wchar_t * fmt, ...)
54
StringCbVPrintf(buf, sizeof(buf), fmt, vl);
55
OutputDebugString(buf);
61
kherr_add_ctx_handler(kherr_ctx_handler h,
69
EnterCriticalSection(&cs_error);
70
if( ctx_handlers == NULL) {
71
nc_ctx_handlers = CTX_ALLOC_INCR;
73
ctx_handlers = PMALLOC(sizeof(*ctx_handlers) * nc_ctx_handlers);
74
/* No need to initialize */
75
} else if (n_ctx_handlers == nc_ctx_handlers) {
77
kherr_handler_node * new_ctxs;
79
new_nc = nc_ctx_handlers + CTX_ALLOC_INCR;
80
new_ctxs = PMALLOC(sizeof(*new_ctxs) * new_nc);
81
memcpy(new_ctxs, ctx_handlers, n_ctx_handlers * sizeof(*new_ctxs));
84
ctx_handlers = new_ctxs;
85
nc_ctx_handlers = new_nc;
89
filter = KHERR_CTX_BEGIN |
96
/* Since commit events are the most frequent, we put those
97
handlers at the top of the list. When dispatching a commit
98
event, we stop looking at the list when we find a filter that
99
doesn't filter for commit events. */
100
if (filter & KHERR_CTX_EVTCOMMIT) {
102
memmove(&ctx_handlers[1], &ctx_handlers[0],
103
n_ctx_handlers * sizeof(ctx_handlers[0]));
105
idx = n_ctx_handlers;
108
ctx_handlers[idx].h = h;
109
ctx_handlers[idx].filter = filter;
110
ctx_handlers[idx].serial = serial;
114
LeaveCriticalSection(&cs_error);
118
kherr_remove_ctx_handler(kherr_ctx_handler h,
122
EnterCriticalSection(&cs_error);
124
for (i=0 ; i < n_ctx_handlers; i++) {
125
if (ctx_handlers[i].h == h &&
126
ctx_handlers[i].serial == serial) {
131
if ( i < n_ctx_handlers ) {
133
for (; i < n_ctx_handlers; i++) {
134
ctx_handlers[i] = ctx_handlers[i + 1];
138
LeaveCriticalSection(&cs_error);
141
/* Called with cs_error held */
143
notify_ctx_event(enum kherr_ctx_event e, kherr_context * c)
149
for (i=0; i<n_ctx_handlers; i++) {
150
if (ctx_handlers[i].h && (ctx_handlers[i].filter & e) &&
151
(ctx_handlers[i].serial == 0 ||
152
ctx_handlers[i].serial == c->serial)) {
153
if (IsBadCodePtr((FARPROC) ctx_handlers[i].h)) {
154
ctx_handlers[i].h = NULL;
156
h = ctx_handlers[i].h;
159
/* a context handler is allowed to remove itself
160
during a callback. It is, however, not allowed to
161
remove anything else. */
162
if (h != ctx_handlers[i].h)
165
} else if (e == KHERR_CTX_EVTCOMMIT &&
166
!(ctx_handlers[i].filter & KHERR_CTX_EVTCOMMIT)) {
167
/* All handlers that filter for commit events are at the
168
top of the list. If this handler wasn't filtering for
169
it, then there's no point in goint further down the
177
attach_this_thread(void)
181
t = (kherr_thread *) TlsGetValue(tls_error);
185
t = PMALLOC(sizeof(kherr_thread) +
186
sizeof(kherr_context *) * THREAD_STACK_SIZE);
187
t->nc_ctx = THREAD_STACK_SIZE;
189
t->ctx = (kherr_context **) &t[1];
191
TlsSetValue(tls_error, t);
195
detach_this_thread(void)
200
t = (kherr_thread *) TlsGetValue(tls_error);
202
for(i=0; i < t->n_ctx; i++) {
203
kherr_release_context(t->ctx[i]);
206
TlsSetValue(tls_error, 0);
210
static kherr_context *
215
t = (kherr_thread *) TlsGetValue(tls_error);
220
c = t->ctx[t->n_ctx - 1];
222
assert(c == NULL || IS_KHERR_CTX(c));
233
push_context(kherr_context * c)
237
t = (kherr_thread *) TlsGetValue(tls_error);
239
attach_this_thread();
240
t = (kherr_thread *) TlsGetValue(tls_error);
244
if (t->n_ctx == t->nc_ctx) {
249
nc_new = t->nc_ctx + THREAD_STACK_SIZE;
250
cb_new = sizeof(kherr_thread) +
251
sizeof(kherr_context *) * nc_new;
253
nt = PMALLOC(cb_new);
254
memcpy(nt, t, sizeof(kherr_thread) +
255
sizeof(kherr_context *) * t->n_ctx);
256
nt->ctx = (kherr_context **) &nt[1];
261
TlsSetValue(tls_error, t);
264
assert(t->n_ctx < t->nc_ctx);
265
t->ctx[t->n_ctx++] = c;
267
kherr_hold_context(c);
270
/* returned pointer is still held */
271
static kherr_context *
277
t = (kherr_thread *) TlsGetValue(tls_error);
280
c = t->ctx[--(t->n_ctx)];
281
assert(IS_KHERR_CTX(c));
291
get_empty_event(void)
295
EnterCriticalSection(&cs_error);
297
LPOP(&evt_free_list, &e);
299
e = PMALLOC(sizeof(*e));
301
LeaveCriticalSection(&cs_error);
302
ZeroMemory(e, sizeof(*e));
303
e->severity = KHERR_NONE;
304
e->magic = KHERR_EVENT_MAGIC;
310
free_event_params(kherr_event * e)
312
assert(IS_KHERR_EVENT(e));
314
if(parm_type(e->p1) == KEPT_STRINGT) {
315
assert((void *) parm_data(e->p1));
316
PFREE((void*) parm_data(e->p1));
318
ZeroMemory(&e->p1, sizeof(e->p1));
320
if(parm_type(e->p2) == KEPT_STRINGT) {
321
assert((void *) parm_data(e->p2));
322
PFREE((void*) parm_data(e->p2));
324
ZeroMemory(&e->p2, sizeof(e->p2));
326
if(parm_type(e->p3) == KEPT_STRINGT) {
327
assert((void *) parm_data(e->p3));
328
PFREE((void*) parm_data(e->p3));
330
ZeroMemory(&e->p3, sizeof(e->p3));
332
if(parm_type(e->p4) == KEPT_STRINGT) {
333
assert((void *) parm_data(e->p4));
334
PFREE((void*) parm_data(e->p4));
336
ZeroMemory(&e->p4, sizeof(e->p4));
340
free_event(kherr_event * e)
342
EnterCriticalSection(&cs_error);
344
assert(IS_KHERR_EVENT(e));
346
assert(LNEXT(e) == NULL);
347
assert(LPREV(e) == NULL);
351
if (!(e->flags & KHERR_RF_STR_RESOLVED))
352
resolve_event_strings(e);
354
if (e->short_desc && e->long_desc) {
355
kherr_debug_printf(L"E:%s (%s)\n", e->short_desc, e->long_desc);
356
} else if (e->short_desc) {
357
kherr_debug_printf(L"E:%s\n", e->short_desc);
358
} else if (e->long_desc) {
359
kherr_debug_printf(L"E:%s\n", e->long_desc);
361
kherr_debug_printf(L"E:[No description for event 0x%p]\n", e);
365
kherr_debug_printf(L" Suggest:[%s]\n", e->suggestion);
367
kherr_debug_printf(L" Facility:[%s]\n", e->facility);
370
if(e->flags & KHERR_RF_FREE_SHORT_DESC) {
371
assert(e->short_desc);
372
PFREE((void *) e->short_desc);
374
if(e->flags & KHERR_RF_FREE_LONG_DESC) {
375
assert(e->long_desc);
376
PFREE((void *) e->long_desc);
378
if(e->flags & KHERR_RF_FREE_SUGGEST) {
379
assert(e->suggestion);
380
PFREE((void *) e->suggestion);
383
free_event_params(e);
385
ZeroMemory(e, sizeof(e));
387
LPUSH(&evt_free_list, e);
388
LeaveCriticalSection(&cs_error);
391
static kherr_context *
392
get_empty_context(void)
396
EnterCriticalSection(&cs_error);
398
LPOP(&ctx_free_list, &c);
400
c = PMALLOC(sizeof(kherr_context));
403
ZeroMemory(c,sizeof(*c));
404
c->severity = KHERR_NONE;
405
c->flags = KHERR_CF_UNBOUND;
406
c->magic = KHERR_CONTEXT_MAGIC;
407
c->serial = ++ctx_serial;
409
LPUSH(&ctx_root_list, c);
411
LeaveCriticalSection(&cs_error);
417
/* Assumes that the context has been deleted from all relevant
420
free_context(kherr_context * c)
425
assert(IS_KHERR_CTX(c));
428
kherr_debug_printf(L"Freeing context 0x%x\n", c);
431
EnterCriticalSection(&cs_error);
434
free_event(c->desc_event);
435
c->desc_event = NULL;
450
LPUSH(&ctx_free_list,c);
451
LeaveCriticalSection(&cs_error);
454
kherr_debug_printf(L"Done with context 0x%x\n", c);
459
add_event(kherr_context * c, kherr_event * e)
463
assert(IS_KHERR_CTX(c));
464
assert(IS_KHERR_EVENT(e));
466
assert(LPREV(e) == NULL && LNEXT(e) == NULL);
469
EnterCriticalSection(&cs_error);
471
if (te && !(te->flags & KHERR_RF_COMMIT)) {
472
notify_ctx_event(KHERR_CTX_EVTCOMMIT, c);
473
te->flags |= KHERR_RF_COMMIT;
477
if(c->severity > e->severity) {
478
if (e->severity <= KHERR_ERROR)
479
notify_ctx_event(KHERR_CTX_ERROR, c);
481
c->severity = e->severity;
483
c->flags &= ~KHERR_CF_DIRTY;
485
LeaveCriticalSection(&cs_error);
489
pick_err_event(kherr_context * c)
492
kherr_event * ce = NULL;
493
enum kherr_severity s;
495
s = KHERR_RESERVED_BANK;
497
EnterCriticalSection(&cs_error);
500
if(!(e->flags & KHERR_RF_INERT) &&
510
c->severity = ce->severity;
513
c->severity = KHERR_NONE;
516
c->flags &= ~KHERR_CF_DIRTY;
517
LeaveCriticalSection(&cs_error);
521
va_arg_from_param(va_list * parm, kherr_param p)
523
int t = parm_type(p);
530
if (t != KEPT_NONE) {
534
pi = (khm_int32 *)(*parm);
535
va_arg(*parm, khm_int32);
536
*pi = (khm_int32) parm_data(p);
541
ps = (wchar_t **) (*parm);
542
va_arg(*parm, wchar_t *);
543
*ps = (wchar_t *) parm_data(p);
547
pptr = (void **) (*parm);
548
va_arg(*parm, void *);
549
*pptr = (void *) parm_data(p);
554
pli = (khm_int64 *) (*parm);
555
va_arg(*parm, khm_int64);
556
*pli = (khm_int64) parm_data(p);
568
va_args_from_event(va_list args, kherr_event * e, khm_size cb)
570
ZeroMemory(args, cb);
572
va_arg_from_param(&args, e->p1);
573
va_arg_from_param(&args, e->p2);
574
va_arg_from_param(&args, e->p3);
575
va_arg_from_param(&args, e->p4);
579
resolve_string_resource(kherr_event * e,
580
const wchar_t ** str,
585
wchar_t tfmt[KHERR_MAXCCH_STRING];
586
wchar_t tbuf[KHERR_MAXCCH_STRING];
590
if(e->flags & if_flag) {
591
if(e->h_module != NULL)
592
chars = LoadString(e->h_module, (UINT)(INT_PTR) *str,
593
tfmt, ARRAYLENGTH(tbuf));
594
if(e->h_module == NULL || chars == 0)
599
chars = FormatMessage(FORMAT_MESSAGE_FROM_STRING, tfmt,
600
0, 0, tbuf, ARRAYLENGTH(tbuf), &vl);
605
bytes = (chars + 1) * sizeof(wchar_t);
608
StringCbCopy(s, bytes, tbuf);
613
e->flags &= ~if_flag;
618
resolve_msg_resource(kherr_event * e,
619
const wchar_t ** str,
624
wchar_t tbuf[KHERR_MAXCCH_STRING];
628
if(e->flags & if_flag) {
629
if(e->h_module != NULL) {
631
chars = FormatMessage(FORMAT_MESSAGE_FROM_HMODULE,
632
(LPCVOID) e->h_module,
633
(DWORD)(DWORD_PTR) *str,
640
if(e->h_module == NULL || chars == 0) {
645
/* MC inserts trailing \r\n to each message unless the
646
message is terminated with a %0. We remove the last
647
line break since it is irrelevant to our handling of
648
the string in the UI. */
649
if (tbuf[chars-1] == L'\n')
650
tbuf[--chars] = L'\0';
651
if (tbuf[chars-1] == L'\r')
652
tbuf[--chars] = L'\0';
654
bytes = (chars + 1) * sizeof(wchar_t);
657
StringCbCopy(s, bytes, tbuf);
661
e->flags &= ~if_flag;
666
resolve_string(kherr_event * e,
667
const wchar_t ** str,
673
wchar_t tbuf[KHERR_MAXCCH_STRING];
677
if (((e->flags & mask) == 0 ||
678
(e->flags & mask) == free_if) &&
681
chars = FormatMessage(FORMAT_MESSAGE_FROM_STRING,
689
if ((e->flags & mask) == free_if) {
690
PFREE((void *) *str);
700
bytes = (chars + 1) * sizeof(wchar_t);
703
StringCbCopy(s, bytes, tbuf);
712
resolve_event_strings(kherr_event * e)
715
va_list vl = (va_list) args;
717
va_args_from_event(vl, e, sizeof(args));
719
resolve_string(e, &e->short_desc, vl,
720
KHERR_RFMASK_SHORT_DESC,
721
KHERR_RF_FREE_SHORT_DESC,
722
KHERR_RF_FREE_SHORT_DESC);
724
resolve_string(e, &e->long_desc, vl,
725
KHERR_RFMASK_LONG_DESC,
726
KHERR_RF_FREE_LONG_DESC,
727
KHERR_RF_FREE_LONG_DESC);
729
resolve_string(e, &e->suggestion, vl,
730
KHERR_RFMASK_SUGGEST,
731
KHERR_RF_FREE_SUGGEST,
732
KHERR_RF_FREE_SUGGEST);
734
resolve_string_resource(e, &e->short_desc, vl,
735
KHERR_RF_RES_SHORT_DESC,
736
KHERR_RF_FREE_SHORT_DESC);
738
resolve_string_resource(e, &e->long_desc, vl,
739
KHERR_RF_RES_LONG_DESC,
740
KHERR_RF_FREE_LONG_DESC);
742
resolve_string_resource(e, &e->suggestion, vl,
743
KHERR_RF_RES_SUGGEST,
744
KHERR_RF_FREE_SUGGEST);
746
resolve_msg_resource(e, &e->short_desc, vl,
747
KHERR_RF_MSG_SHORT_DESC,
748
KHERR_RF_FREE_SHORT_DESC);
749
resolve_msg_resource(e, &e->long_desc, vl,
750
KHERR_RF_MSG_LONG_DESC,
751
KHERR_RF_FREE_LONG_DESC);
752
resolve_msg_resource(e, &e->suggestion, vl,
753
KHERR_RF_MSG_SUGGEST,
754
KHERR_RF_FREE_SUGGEST);
756
/* get rid of dangling reference now that we have done everything
757
we can with it. Since we have already dealt with all the
758
parameter inserts, we don't need the parameters anymore
760
free_event_params(e);
763
e->flags |= KHERR_RF_STR_RESOLVED;
768
kherr_evaluate_event(kherr_event * e)
770
if (!IS_KHERR_EVENT(e))
773
EnterCriticalSection(&cs_error);
774
resolve_event_strings(e);
775
LeaveCriticalSection(&cs_error);
779
kherr_evaluate_last_event(void)
788
tid = GetCurrentThreadId();
790
EnterCriticalSection(&cs_error);
792
while (e != NULL && e->thread_id != tid)
795
if(!IS_KHERR_EVENT(e))
798
resolve_event_strings(e);
801
LeaveCriticalSection(&cs_error);
804
KHMEXP kherr_event * __cdecl
805
kherr_reportf(const wchar_t * long_desc_fmt, ...)
811
va_start(vl, long_desc_fmt);
812
StringCbVPrintf(buf, sizeof(buf), long_desc_fmt, vl);
814
OutputDebugString(buf);
818
e = kherr_report(KHERR_DEBUG_1,
819
NULL, NULL, NULL, buf, NULL, 0,
820
KHERR_SUGGEST_NONE, _vnull(), _vnull(), _vnull(), _vnull(),
821
KHERR_RF_CSTR_LONG_DESC
826
if (IS_KHERR_EVENT(e)) {
827
kherr_evaluate_event(e);
833
KHMEXP kherr_event * __cdecl
834
kherr_reportf_ex(enum kherr_severity severity,
835
const wchar_t * facility,
836
khm_int32 facility_id,
840
const wchar_t * long_desc_fmt, ...)
846
va_start(vl, long_desc_fmt);
847
StringCbVPrintf(buf, sizeof(buf), long_desc_fmt, vl);
849
OutputDebugString(buf);
853
e = kherr_report(severity, NULL, facility, NULL, buf, NULL, facility_id,
858
_vnull(), KHERR_RF_CSTR_LONG_DESC
863
if (IS_KHERR_EVENT(e)) {
864
kherr_evaluate_event(e);
870
KHMEXP kherr_event * KHMAPI
871
kherr_report(enum kherr_severity severity,
872
const wchar_t * short_desc,
873
const wchar_t * facility,
874
const wchar_t * location,
875
const wchar_t * long_desc,
876
const wchar_t * suggestion,
877
khm_int32 facility_id,
878
enum kherr_suggestion suggestion_id,
891
khm_boolean invalid = FALSE;
894
if (!IS_POW2(flags & KHERR_RFMASK_SHORT_DESC) ||
895
!IS_POW2(flags & KHERR_RFMASK_LONG_DESC) ||
896
!IS_POW2(flags & KHERR_RFMASK_SUGGEST))
899
e = get_empty_event();
901
e->thread_id = GetCurrentThreadId();
902
e->time_ticks = GetTickCount();
903
GetSystemTimeAsFileTime(&e->time_ft);
905
e->severity = severity;
906
e->short_desc = short_desc;
907
e->facility = facility;
908
e->location = location;
909
e->long_desc = long_desc;
910
e->suggestion = suggestion;
911
e->facility_id = facility_id;
912
e->suggestion_id = suggestion_id;
919
e->h_module = h_module;
922
EnterCriticalSection(&cs_error);
926
/* the reason why we are doing it this way is because p1..p4,
927
the descriptions and the suggestion may contain allocations
928
that has to be freed. */
935
LeaveCriticalSection(&cs_error);
941
kherr_suggest(wchar_t * suggestion,
942
enum kherr_suggestion suggestion_id,
949
if (flags != KHERR_RF_CSTR_SUGGEST &&
950
flags != KHERR_RF_RES_SUGGEST &&
951
flags != KHERR_RF_MSG_SUGGEST &&
952
flags != KHERR_RF_FREE_SUGGEST)
959
tid = GetCurrentThreadId();
961
EnterCriticalSection(&cs_error);
963
while (e != NULL && e->thread_id != tid)
966
if(!IS_KHERR_EVENT(e))
969
/* if strings have already been resolved in this event, we cant
970
add any more unresolved strings. */
971
if ((flags == KHERR_RF_RES_SUGGEST ||
972
flags == KHERR_RF_MSG_SUGGEST) &&
973
(e->flags & KHERR_RF_STR_RESOLVED))
976
e->suggestion = suggestion;
977
e->suggestion_id = suggestion_id;
980
LeaveCriticalSection(&cs_error);
984
kherr_location(wchar_t * location)
993
tid = GetCurrentThreadId();
995
EnterCriticalSection(&cs_error);
997
while (e != NULL && e->thread_id != tid)
1000
if(!IS_KHERR_EVENT(e))
1002
e->location = location;
1004
LeaveCriticalSection(&cs_error);
1008
kherr_facility(wchar_t * facility,
1009
khm_int32 facility_id)
1016
if(!IS_KHERR_CTX(c))
1018
tid = GetCurrentThreadId();
1019
EnterCriticalSection(&cs_error);
1021
while (e != NULL && e->thread_id != tid)
1024
if(!IS_KHERR_EVENT(e))
1026
e->facility = facility;
1027
e->facility_id = facility_id;
1029
LeaveCriticalSection(&cs_error);
1033
kherr_set_desc_event(void)
1040
if(!IS_KHERR_CTX(c))
1042
tid = GetCurrentThreadId();
1044
EnterCriticalSection(&cs_error);
1046
while (e != NULL && e->thread_id != tid)
1049
if(!IS_KHERR_EVENT(e) || c->desc_event)
1054
e->severity = KHERR_NONE;
1055
resolve_event_strings(e);
1057
notify_ctx_event(KHERR_CTX_DESCRIBE, c);
1060
LeaveCriticalSection(&cs_error);
1064
kherr_del_last_event(void)
1072
if(!IS_KHERR_CTX(c))
1075
tid = GetCurrentThreadId();
1077
EnterCriticalSection(&cs_error);
1079
while (e != NULL && e->thread_id != tid)
1082
if(IS_KHERR_EVENT(e)) {
1084
if(c->err_event == e) {
1089
LeaveCriticalSection(&cs_error);
1093
kherr_push_context(kherr_context * c)
1095
kherr_context * p = NULL;
1096
int new_context = FALSE;
1098
if (!IS_KHERR_CTX(c))
1101
EnterCriticalSection(&cs_error);
1103
if(IS_KHERR_CTX(p) && (c->flags & KHERR_CF_UNBOUND)) {
1104
LDELETE(&ctx_root_list, c);
1106
c->flags &= ~KHERR_CF_UNBOUND;
1107
kherr_hold_context(p);
1112
if (new_context && IS_KHERR_CTX(p)) {
1113
notify_ctx_event(KHERR_CTX_BEGIN, c);
1114
notify_ctx_event(KHERR_CTX_NEWCHILD, p);
1117
LeaveCriticalSection(&cs_error);
1121
kherr_push_new_context(khm_int32 flags)
1123
kherr_context * p = NULL;
1126
flags &= KHERR_CFMASK_INITIAL;
1128
EnterCriticalSection(&cs_error);
1130
c = get_empty_context();
1131
if(IS_KHERR_CTX(p)) {
1132
LDELETE(&ctx_root_list, c);
1134
c->flags &= ~KHERR_CF_UNBOUND;
1135
kherr_hold_context(p);
1140
notify_ctx_event(KHERR_CTX_BEGIN, c);
1141
if (IS_KHERR_CTX(p)) {
1142
notify_ctx_event(KHERR_CTX_NEWCHILD, p);
1145
LeaveCriticalSection(&cs_error);
1149
dup_parm(kherr_param p)
1151
if(parm_type(p) == KEPT_STRINGT) {
1152
wchar_t * d = PWCSDUP((wchar_t *)parm_data(p));
1153
return kherr_val(KEPT_STRINGT, (khm_ui_8) d);
1158
static kherr_event *
1159
fold_context(kherr_context * c)
1164
if (!IS_KHERR_CTX(c))
1167
EnterCriticalSection(&cs_error);
1168
if(!c->err_event || (c->flags & KHERR_CF_DIRTY)) {
1173
e = get_empty_event();
1175
g->short_desc = NULL;
1176
g->long_desc = NULL;
1177
g->suggestion = NULL;
1179
~(KHERR_RF_FREE_SHORT_DESC |
1180
KHERR_RF_FREE_LONG_DESC |
1181
KHERR_RF_FREE_SUGGEST);
1183
e->p1 = dup_parm(g->p1);
1184
e->p2 = dup_parm(g->p2);
1185
e->p3 = dup_parm(g->p3);
1186
e->p4 = dup_parm(g->p4);
1189
c->desc_event = NULL;
1192
if (IS_KHERR_EVENT(e))
1193
e->flags |= KHERR_RF_CONTEXT_FOLD;
1195
LeaveCriticalSection(&cs_error);
1201
kherr_hold_context(kherr_context * c)
1203
if(!IS_KHERR_CTX(c))
1206
EnterCriticalSection(&cs_error);
1208
LeaveCriticalSection(&cs_error);
1212
kherr_release_context(kherr_context * c)
1214
if (!IS_KHERR_CTX(c))
1217
EnterCriticalSection(&cs_error);
1219
if (c->refcount == 0) {
1224
if (IS_KHERR_EVENT(e) && !(e->flags & KHERR_RF_COMMIT)) {
1225
notify_ctx_event(KHERR_CTX_EVTCOMMIT, c);
1226
e->flags |= KHERR_RF_COMMIT;
1229
notify_ctx_event(KHERR_CTX_END, c);
1232
if (IS_KHERR_CTX(p)) {
1233
e = fold_context(c);
1239
notify_ctx_event(KHERR_CTX_FOLDCHILD, p);
1241
kherr_release_context(p);
1243
LDELETE(&ctx_root_list, c);
1247
LeaveCriticalSection(&cs_error);
1251
kherr_pop_context(void)
1255
EnterCriticalSection(&cs_error);
1257
if(IS_KHERR_CTX(c)) {
1258
kherr_release_context(c);
1260
LeaveCriticalSection(&cs_error);
1263
KHMEXP kherr_context * KHMAPI
1264
kherr_peek_context(void)
1269
if (IS_KHERR_CTX(c))
1270
kherr_hold_context(c);
1275
KHMEXP khm_boolean KHMAPI
1276
kherr_is_error(void)
1278
kherr_context * c = peek_context();
1279
return kherr_is_error_i(c);
1282
KHMEXP khm_boolean KHMAPI
1283
kherr_is_error_i(kherr_context * c)
1285
if(IS_KHERR_CTX(c) && c->severity <= KHERR_ERROR)
1292
kherr_clear_error(void)
1294
kherr_context * c = peek_context();
1295
if (IS_KHERR_CTX(c))
1296
kherr_clear_error_i(c);
1300
kherr_clear_error_i(kherr_context * c)
1303
if (IS_KHERR_CTX(c)) {
1304
EnterCriticalSection(&cs_error);
1307
assert(IS_KHERR_EVENT(e));
1309
e->flags |= KHERR_RF_INERT;
1312
c->severity = KHERR_NONE;
1313
c->err_event = NULL;
1314
c->flags &= ~KHERR_CF_DIRTY;
1315
LeaveCriticalSection(&cs_error);
1319
/* does the context 'c' use it's own progress marker? If this is
1320
false, the progress marker for the context is derived from the
1321
progress markers of its children. */
1322
#define CTX_USES_OWN_PROGRESS(c) ((c)->progress_num != 0 || (c)->progress_denom != 0 || ((c)->flags & KHERR_CF_OWN_PROGRESS))
1325
kherr_set_progress(khm_ui_4 num, khm_ui_4 denom)
1327
kherr_context * c = peek_context();
1328
if(IS_KHERR_CTX(c)) {
1329
EnterCriticalSection(&cs_error);
1334
if (c->progress_denom != denom ||
1335
c->progress_num != denom) {
1339
c->progress_denom = denom;
1340
c->progress_num = num;
1342
notify_ctx_event(KHERR_CTX_PROGRESS, c);
1344
for (p = TPARENT(c);
1345
IS_KHERR_CTX(p) && !CTX_USES_OWN_PROGRESS(p);
1348
notify_ctx_event(KHERR_CTX_PROGRESS, p);
1352
LeaveCriticalSection(&cs_error);
1357
kherr_get_progress(khm_ui_4 * num, khm_ui_4 * denom)
1359
kherr_context * c = peek_context();
1360
kherr_get_progress_i(c,num,denom);
1363
/* called with cs_error held */
1365
get_progress(kherr_context * c, khm_ui_4 * pnum, khm_ui_4 * pdenom)
1367
if (CTX_USES_OWN_PROGRESS(c)) {
1368
*pnum = c->progress_num;
1369
*pdenom = c->progress_denom;
1376
for (cc = TFIRSTCHILD(c);
1380
khm_ui_4 cnum, cdenom;
1382
assert(IS_KHERR_CTX(cc));
1384
get_progress(cc, &cnum, &cdenom);
1392
if (cdenom != 256) {
1393
cnum = (cnum * 256) / cdenom;
1408
kherr_get_progress_i(kherr_context * c,
1412
if (num == NULL || denom == NULL)
1415
if(IS_KHERR_CTX(c)) {
1416
EnterCriticalSection(&cs_error);
1417
get_progress(c, num, denom);
1418
LeaveCriticalSection(&cs_error);
1425
KHMEXP kherr_event * KHMAPI
1426
kherr_get_first_event(kherr_context * c)
1430
if (!IS_KHERR_CTX(c))
1433
EnterCriticalSection(&cs_error);
1435
LeaveCriticalSection(&cs_error);
1436
assert(e == NULL || IS_KHERR_EVENT(e));
1440
KHMEXP kherr_event * KHMAPI
1441
kherr_get_next_event(kherr_event * e)
1445
if (!IS_KHERR_EVENT(e))
1448
EnterCriticalSection(&cs_error);
1450
LeaveCriticalSection(&cs_error);
1451
assert(ee == NULL || IS_KHERR_EVENT(ee));
1455
KHMEXP kherr_event * KHMAPI
1456
kherr_get_prev_event(kherr_event * e)
1460
if (!IS_KHERR_EVENT(e))
1463
EnterCriticalSection(&cs_error);
1465
LeaveCriticalSection(&cs_error);
1466
assert(ee == NULL || IS_KHERR_EVENT(ee));
1470
KHMEXP kherr_event * KHMAPI
1471
kherr_get_last_event(kherr_context * c)
1475
if (!IS_KHERR_CTX(c))
1478
EnterCriticalSection(&cs_error);
1480
LeaveCriticalSection(&cs_error);
1481
assert(e == NULL || IS_KHERR_EVENT(e));
1485
KHMEXP kherr_context * KHMAPI
1486
kherr_get_first_context(kherr_context * c)
1490
if (c != NULL && !IS_KHERR_CTX(c))
1493
EnterCriticalSection(&cs_error);
1494
if (IS_KHERR_CTX(c)) {
1495
cc = TFIRSTCHILD(c);
1497
kherr_hold_context(cc);
1501
kherr_hold_context(cc);
1503
LeaveCriticalSection(&cs_error);
1504
assert(cc == NULL || IS_KHERR_CTX(cc));
1508
KHMEXP kherr_context * KHMAPI
1509
kherr_get_next_context(kherr_context * c)
1513
if (!IS_KHERR_CTX(c))
1516
EnterCriticalSection(&cs_error);
1519
kherr_hold_context(cc);
1520
LeaveCriticalSection(&cs_error);
1521
assert(cc == NULL || IS_KHERR_CTX(cc));
1525
KHMEXP kherr_event * KHMAPI
1526
kherr_get_err_event(kherr_context * c)
1530
if (!IS_KHERR_CTX(c))
1533
EnterCriticalSection(&cs_error);
1538
LeaveCriticalSection(&cs_error);
1539
assert(e == NULL || IS_KHERR_EVENT(e));
1543
KHMEXP kherr_event * KHMAPI
1544
kherr_get_desc_event(kherr_context * c)
1548
if (!IS_KHERR_CTX(c))
1551
EnterCriticalSection(&cs_error);
1553
LeaveCriticalSection(&cs_error);
1554
assert(e == NULL || IS_KHERR_EVENT(e));
1559
kherr_dup_string(const wchar_t * s)
1567
if (FAILED(StringCbLength(s, KHERR_MAXCB_STRING, &cb_s)))
1568
cb_s = KHERR_MAXCB_STRING;
1570
cb_s += sizeof(wchar_t);
1572
dest = PMALLOC(cb_s);
1573
assert(dest != NULL);
1576
StringCbCopy(dest, cb_s, s);