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
#ifndef __KHIMAIRA_KHERR_H
28
#define __KHIMAIRA_KHERR_H
30
/*! \defgroup kherr NetIDMgr Error Reporting
32
Error reporting functions provide a mechanism to construct
33
meaningful and user friendly error reports for the user.
35
Unlike most of the other NetIDMgr API's, the error reporting APIs
36
are lightweight and usually do not return an error value. This is
37
mostly because, these functions are called \b after an error
44
/*! \name Customizable macros
46
#ifndef KHERR_FACILITY
47
/*! \brief The default facility when reporting errors
49
When including this header file, if the KHERR_FACILITY macro is
50
defined to be a wide character string, then it will be used as the
51
default facility when for the convenience macros. All of the
52
calls to the convenience macros in the source file would then have
55
If left undefined, the convenience macros will leave the facility
58
#define KHERR_FACILITY NULL
61
#ifndef KHERR_FACILITY_ID
62
/*! \brief The default facility ID when reporting errors
64
When including this header file, if the KHERR_FACILITY_ID macro is
65
defined to be non-zero, then it will be used as the default
66
facility identifier for the convenience macros. All of the calls
67
to the convenience macros in the source file would then have that
70
The default value of 0 means that the facility is undefined.
72
#define KHERR_FACILITY_ID 0
75
/*! \define KHERR_HMODULE (undefined)
76
\brief The default module handle
78
When including this header file, if the KHERR_HMODULE macro is
79
defined to be an identifier that holds the module handle, then the
80
convenience macros that specify a module handle will use it.
82
A default value is not defined for KHERR_HMODULE. Any attempt to
83
invoke any of the convenience macros that use it should generate a
92
/*! \brief Parameter types
94
enum kherr_parm_types {
100
KEPT_STRINGC, /*!< String constant */
101
KEPT_STRINGT, /*!< String. Will be freed using
102
free() when the event is freed */
103
KEPT_PTR /*!< Pointer type. */
107
typedef struct tag_kherr_param {
112
/*! \brief Severity levels
114
Larger the value, the less severe it is.
116
enum tag_kherr_severity {
117
KHERR_FATAL = 0, /*!< Fatal error.*/
118
KHERR_ERROR, /*!< Non-fatal error. We'll probably
119
survive. See the suggested action. */
120
KHERR_WARNING, /*!< Warning. Something almost broke
121
or soon will. See the suggested
123
KHERR_INFO, /*!< Informational. Something happened
124
that we would like you to know
126
KHERR_DEBUG_1 = 64, /*!< Verbose debug level 1 (high)
127
Events at this severity level are
128
not required to be based on
129
localized strings. */
130
KHERR_DEBUG_2 = 65, /*!< Verbose debug level 2 (medium)
131
Events at this severity level are
132
not required to be based on
133
localized strings. */
134
KHERR_DEBUG_3 = 66, /*!< Verbose debug level 3 (low)
135
Events at this severity level are
136
not required to be based on
137
localized strings. */
138
KHERR_RESERVED_BANK = 127, /*!< Internal use */
139
KHERR_NONE = 128 /*!< Nothing interesting has happened
143
typedef enum tag_kherr_severity kherr_severity;
145
/*! \brief Suggestions */
146
enum tag_kherr_suggestion {
147
KHERR_SUGGEST_NONE = 0, /*!< No suggestions. */
148
KHERR_SUGGEST_ABORT, /*!< Abort whatever it was you were
149
trying. It's not gonna work. */
150
KHERR_SUGGEST_RETRY, /*!< Retry. It might work the second
151
or third time over */
152
KHERR_SUGGEST_IGNORE, /*!< Ignore. It might go away. */
153
KHERR_SUGGEST_INTERACT, /*!< Further user interaction is
154
necessary to resolve the situation.
155
The suggest string in the event
156
should be prompted to the user. */
157
KHERR_SUGGEST_OTHER, /*!< Something else. */
160
typedef enum tag_kherr_suggestion kherr_suggestion;
162
/*! \brief An event */
163
typedef struct tag_kherr_event {
164
khm_int32 magic; /*!< Magic number. Always set to
166
DWORD thread_id; /*!< The thread which reported this
168
const wchar_t * short_desc; /*!< Short description or title
170
const wchar_t * facility; /*!< Facility name of the reporter
172
const wchar_t * location; /*!< Location. Usually the function
173
name or such of where the event
174
occured (not localized) */
175
const wchar_t * long_desc; /*!< A long description of what went
176
wrong (localized, formatted) */
177
const wchar_t * suggestion; /*!< A suggested way to fix it
178
(localized,formatted) */
180
kherr_severity severity;
181
/*!< Severity level. One of the
182
severity levels listed in
183
enumeration ::kherr_severity */
184
khm_int32 facility_id; /*!< Left to the application to
186
kherr_suggestion suggestion_id;
187
/*!< One of the suggestion ID's from
189
::kherr_suggestion */
191
int flags; /*!< Flags. */
193
kherr_param p1; /*!< Parameter 1 for formatting */
194
kherr_param p2; /*!< Parameter 2 for formatting */
195
kherr_param p3; /*!< Parameter 3 for formatting */
196
kherr_param p4; /*!< Parameter 4 for formatting */
198
DWORD time_ticks; /*!< Time at which event was reported
199
(as returned by GetTickCount(). */
200
FILETIME time_ft; /*!< Time at which event was reported.
201
Current system time as FILETIME. */
204
HMODULE h_module; /*!< Handle to the module which should
205
resolve any unresolved resources
209
LDCL(struct tag_kherr_event);
212
#define KHERR_EVENT_MAGIC 0x0423e84f
214
/*! \brief Flags for kherr_event
216
Each set of flags that define the type of resource for one value
217
is mutually exclusive.
219
enum kherr_event_flags {
220
KHERR_RF_CSTR_SHORT_DESC= 0x00000000,
221
/*!< Short description is a constant
223
KHERR_RF_RES_SHORT_DESC = 0x00000001,
224
/*!< Short description is a string
226
KHERR_RF_MSG_SHORT_DESC = 0x00000002,
227
/*!< Short description is a message
229
KHERR_RF_FREE_SHORT_DESC= 0x00000004,
230
/*!< Short description is an allocated
232
KHERR_RFMASK_SHORT_DESC = 0x00000007,
234
KHERR_RF_CSTR_LONG_DESC = 0x00000000,
235
/*!< Long description is a constant
237
KHERR_RF_RES_LONG_DESC = 0x00000008,
238
/*!< Long description is a string
240
KHERR_RF_MSG_LONG_DESC = 0x00000010,
241
/*!< Long description is a message
243
KHERR_RF_FREE_LONG_DESC = 0x00000020,
244
/*!< Long description is an allocated
246
KHERR_RFMASK_LONG_DESC = 0x00000038,
248
KHERR_RF_CSTR_SUGGEST = 0x00000000,
249
/*!< Suggestion is a constant
251
KHERR_RF_RES_SUGGEST = 0x00000040,
252
/*!< Suggestion is a string
254
KHERR_RF_MSG_SUGGEST = 0x00000080,
255
/*!< Suggestion is a message
257
KHERR_RF_FREE_SUGGEST = 0x00000100,
258
/*!< Suggestion is an allocated
260
KHERR_RFMASK_SUGGEST = 0x000001C0,
262
KHERR_RF_STR_RESOLVED = 0x00010000,
263
/*!< The string resources in the event
264
have been resolved. */
265
KHERR_RF_CONTEXT_FOLD = 0x00020000,
266
/*!< The event is a representation of
269
KHERR_RF_INERT = 0x00040000,
270
/*!< Inert event. The event has
271
already been dealt with and is no
272
longer considered significant. */
273
KHERR_RF_COMMIT = 0x00080000
274
/*!< Committed event. The commit
275
handlers for this event have already
279
/*! \brief Serial number for error contexts */
280
typedef khm_ui_4 kherr_serial;
282
/*! \brief An error context
284
typedef struct tag_kherr_context {
285
khm_int32 magic; /*!< Magic number. Always set to
286
KHERR_CONTEXT_MAGIC */
288
kherr_serial serial; /*!< Context instance serial number.
289
Context objects themselves may be
290
reused for different contexts as
291
they are freed and reallocated.
292
However every instance of a context
293
is guaranteed to have a unique
294
serial number as specified in this
295
field. If an external entity wants
296
to keep track of the context, it
297
should keep track of the serial
298
number as well as the pointer to the
301
kherr_severity severity;
302
/*!< Severity level. One of the
303
severity levels listed below. This
304
is the severity level of the context
305
and is the maximum severity level of
306
all the events in the queue of
309
khm_int32 flags; /*!< Flags. Used internally. */
310
khm_ui_4 refcount; /*!< Reference count. Used
313
kherr_event *desc_event; /*!< Description event. The event that
314
describes the error context. This
315
points to an event that is not in
318
kherr_event *err_event; /*!< Significant event. The last one
319
that caused the severity level to be
320
what it is right now. This points
321
to an event that is listed in the
322
event queue for this context.*/
324
khm_ui_4 progress_num; /*!< Progress numerator */
325
khm_ui_4 progress_denom; /*!< Progress denominator */
327
TDCL(struct tag_kherr_context);
328
QDCL(struct tag_kherr_event);
331
#define KHERR_CONTEXT_MAGIC 0x34f3238c
333
enum kherr_context_flags {
334
KHERR_CF_NONE = 0x00000000,
337
KHERR_CF_DIRTY = 0x00000001,
338
/*!< Used Internally. Denotes that
339
the err_event and severity may need
340
to be recalculated. Cannot be set
341
as an initial flag. */
343
KHERR_CF_OWN_PROGRESS = 0x00000002,
344
/*!< The context maintains its own
345
progress meter as opposed to one
346
that is derived from child
349
KHERR_CF_UNBOUND = 0x00000004,
350
/*!< Unbound context. The context
351
can't be used to log events. Call
352
kherr_push_context() to associate
353
the context with the global context
354
hierarchy. Cannot be set as an
357
KHERR_CF_TRANSITIVE = 0x00000008,
358
/*!< Transitive. The context is
359
automatically made the current
360
context for all other threads that
361
handle messages sent or posted by
362
threads whose current error context
365
KHERR_CFMASK_INITIAL = 0x0000000a,
366
/*!< Allowed initial flags */
369
/*! \brief Maximum length of a string field in characters including terminating NULL
371
#define KHERR_MAXCCH_STRING 1024
373
/*! \brief Maximum length of a string field in bytes including terminating NULL
375
#define KHERR_MAXCB_STRING (KHERR_MAXCCH_STRING * sizeof(wchar_t))
377
/*! \brief Context event
379
\see kherr_add_ctx_handler()
381
enum kherr_ctx_event {
382
KHERR_CTX_BEGIN = 0x00000001, /*!< A new context was created */
383
KHERR_CTX_DESCRIBE = 0x00000002, /*!< A context was described */
384
KHERR_CTX_END = 0x00000004, /*!< A context was closed */
385
KHERR_CTX_ERROR = 0x00000008, /*!< A context switched to an
387
KHERR_CTX_EVTCOMMIT = 0x00000010, /*!< A event was committed into
389
KHERR_CTX_NEWCHILD = 0x00000020, /*!< A new child context was created */
390
KHERR_CTX_FOLDCHILD = 0x00000040, /*!< A child context was folded */
391
KHERR_CTX_PROGRESS = 0x00000080, /*!< Progress marker updated for context */
394
/*! \brief Context event handler
396
Context event handlers are invoked when specific events occur with
397
respect to an error context. The ::kherr_ctx_event parameter
398
specifies which event occurred using one of the event values
399
described in the enumeration. The error context in which this
400
event occurred is specified by the ::kherr_context pointer.
402
Note that if the handler needs to keep track of the error context
403
for later processing, it also needs to keep track of the \a serial
404
field of the error context. The same context object may be
405
reused, but the serial number is guaranteed to be unique.
407
\see kherr_add_ctx_handler()
409
typedef void (KHMAPI * kherr_ctx_handler)(enum kherr_ctx_event,
412
/*! \brief Add a context event handler
414
An application can register an event handler that gets notified of
415
events that pertain to error contexts. More than one handler can
416
be registered. The order in which the handlers are called is
417
undefined for any specific event.
419
These event occur in the context of individual application
420
threads. The handler will be called from within the thread that
421
caused the event. Therefore it is important that the handler is
422
both reentrant and returns quickly.
424
The events that the handler will be notified of are explained
427
<b>KHERR_CTX_BEGIN</b>: Notification that a new context was
428
created. A pointer to the context will be supplied to the
429
handler. The supplied pointer should not be used to obtain a hold
430
on the context, as it will prevent the context from being closed.
432
<b>KHERR_CTX_DESCRIBE</b>: The thread called
433
kherr_set_desc_event() to set the description of a context. Once
434
again, the pointer should not be used to obtain a hold on the
437
<b>KHERR_CTX_ERROR</b>: The last event that was reported for the
438
context was an error event (the severity was was equal or higher
439
than KHERR_ERROR). The pointer may be used to obtain a hold on
440
the context. However, it is the application's resonsibility to
441
make sure that the hold is released later. Otherwise the event
442
will never be closed.
444
<b>KHERR_CTX_END</b>: Closure. This event is signalled when the
445
last open handle to the context is closed and there is no thread
446
that is currently active which has this context in its error
447
context stack. At the time the handler is invoked, the context is
448
still intact. The pointer that is supplied should not be used to
449
obtain a handle on the context.
451
<b>KHERR_CTX_EVTCOMMIT</b>: An event was committed into the error
452
context. An event is committed when another event is reported
453
after the event, or if the context is closed. Since the last
454
event that is reported can still be modified by adding new
455
information, the event remains open until it is no longer the last
456
event or the context is no longer active. When this notification
457
is received, the last event in the context's event queue is the
458
event that was committed.
460
\param[in] h Context event handler, of type ::kherr_ctx_handler
462
\param[in] filter A combination of ::kherr_ctx_event values
463
indication which notifications should be sent to the handler.
464
If a \a filter value of zero is provided, all of the events
465
will be sent to the handler.
467
\param[in] serial The serial number of the error context that
468
should be tracked. If this is zero, all error contexts can
471
KHMEXP void KHMAPI kherr_add_ctx_handler(kherr_ctx_handler h,
473
kherr_serial serial);
475
/*! \brief Remove a context event handler
477
Undoes what was done with kherr_add_ctx_handler()
479
\see kherr_add_ctx_handler()
481
KHMEXP void KHMAPI kherr_remove_ctx_handler(kherr_ctx_handler h,
482
kherr_serial serial);
485
/*! \brief Report an error
487
Creates an event, fills in the details specified in the arguments,
488
and adds it to the current error context.
490
If the current thread does not have an error context, no reporting
491
happens. However, if any of the supplied strings or parameters
492
are marked as allocated, they will be freed before the function
495
Certain parameters that expect strings can instead be given string
496
resources, message resources or allocated strings in addition to
497
constant string. By default, the parameters are expected to be
500
<b>Allocated strings</b>: The application can allocate memory for
501
a string. Since the application is not notified when the event is
502
no longer used and freed, it \b must indicate that the string is
503
an allocated string by setting the appropriate flag in the \a
504
flags parameter. When the event is no longer used, the memory
505
pointed to by the relevant pointer will be freed through a call to
506
free(). Not all string parameters take allocated strings. See
507
individual parameter documentation for details.
509
<b>String resources</b>: On WIN32, string resources can be passed
510
in to kherr_report() using the MAKEINTRESOURCE macro. However,
511
the application \b must specify that the parameter is a string
512
resource using the appropriate flag in the \a flags parameter.
513
The error reporting engine will expand the string against the
514
module handle passed in the \a h_module parameter when the value
515
of the string is required. Not all string parameters take string
516
resources. See individual parameter documentation for details.
517
Strings loaded through string resources cannot be longer than
518
::KHERR_MAXCCH_STRING in characters inclusive of terminating NULL.
520
<b>Message resources</b>: On WIN32, message resources can be
521
passed in to kherr_report() by specifying the message ID where it
522
ordinarily expects a pointer to a constant string. The
523
application \b must indicate that the string is a message resource
524
by using the appropriate flag in the \a flags parameter. When the
525
value of the string is needed, it is expanded against the module
526
handle passed in the \a h_module parameter using the message ID.
527
Not all string parameters take message resources. See individual
528
parameter documentation for details. Note that the facility and
529
severity values associated with a message resource are ignored.
530
Strings loaded through message resources cannot be longer than
531
::KHERR_MAXCCH_STRING in characters inclusive of terminating NULL.
533
<b>Formatted fields</b>: Parameters that are formatted can have
534
can have parameter inserts like in printf(). However, specifying
535
inserts is different from printf() and follows the conventions
536
used in WIN32 API FormatMessage(). This is because for localized
537
strings, the order of the parameters in the string may be
538
different. See the documentation for FormatMessage() for details
539
on the format string. The same set of parameters (i.e. \a p1, \a
540
p2, \a p3, \a p4) is used for all formatted strings with
541
appropriate marshalling for 64 bit types. The size of the string
542
after expansion must not exceed 65536 bytes inclusive of
545
\param[in] severity One of ::kherr_severity_level
546
\param[in] short_desc Short description or title (localized). Can
547
be a string resource, message resource, allocated string or
548
constant string. The \a flags parameter should indicate the
550
\param[in] facility Facility name of the reporter (not localized)
551
\param[in] location Usually the function name or such of where the
552
event occured (not localized)
553
\param[in] long_desc Long description of event (localized,
554
formatted). Can be a string resource, message resource,
555
allocated string or constant string. The \a flags parameter
556
should indicate the type of string used.
557
\param[in] suggestion Suggested action to correct situation, if
558
applicable (localized). Can be a string resource, message
559
resource, allocated string or constant string. The \a flags
560
parameter should indicate the type of string used.
561
\param[in] facility_id Identifier of facility. Application
563
\param[in] suggestion_id One of the suggestion identifiers from
564
::kherr_suggestion_ids
565
\param[in] p1 First parameter. Used for formatting.
566
\param[in] p2 Second parameter. Used for formatting.
567
\param[in] p3 Third parameter. Used for formatting.
568
\param[in] p4 Fourth parameter. Used for formatting.
569
\param[in] flags Flags. See ::kherr_report_flags
570
\param[in] h_module Handle to a module that resolves any string or
571
message resources used for the \a short_description , \a
572
long_desc or \a suggestion parameters. This parameter is only
575
\note With the exception of parameters of type KEPT_STRINGT and
576
parameters which are flagged for freeing using the \a flags
577
parameter, all other string parameters are assumed to be
578
pointers to constant strings. The strings are not copied and
579
the pointers are used as is. Also, no clean-up is performed
580
when the event is freed other than that implied by \a flags.
582
KHMEXP kherr_event * KHMAPI kherr_report(
583
kherr_severity severity,
584
const wchar_t * short_desc,
585
const wchar_t * facility,
586
const wchar_t * location,
587
const wchar_t * long_desC,
588
const wchar_t * suggestion,
589
khm_int32 facility_id,
590
kherr_suggestion suggestion_id,
601
/*! \brief Report a formatted message
603
The format string \a long_desc_fmt should be a string constant and
604
the format specifiers follow that of \a sprintf. This creates an
605
event with the long description set to the expansion of the format
606
string against the arguments.
608
KHMEXP kherr_event * __cdecl
609
kherr_reportf_ex(kherr_severity severity,
610
const wchar_t * facility,
611
khm_int32 facility_id,
615
const wchar_t * long_desc_fmt,
617
#define _reportf_ex kherr_reportf_ex
619
/*! \brief Report a formatted message
621
The format string \a long_desc_fmt should be a string constant and
622
the format specifiers follow that of \a sprintf. This creates an
623
event with the long description set to the expansion of the format
624
string against the arguments.
626
KHMEXP kherr_event * __cdecl
627
kherr_reportf(const wchar_t * long_desc_fmt,
629
#define _reportf kherr_reportf
631
/*! \brief Create a parameter out of a transient string
633
A parameter is created by duplicating the string that is passed
634
into the function. If the string exceeds KHERR_MAXCCH_STRING,
635
then only the first part of the string that fits within the limit
638
The resulting ::kherr_param must be passed in to kherr_report().
639
The event logging framework will free the duplicated string once
640
the data is no longer required.
642
KHMEXP kherr_param kherr_dup_string(const wchar_t * s);
644
__inline KHMEXP kherr_param
645
kherr_val(khm_octet ptype, khm_ui_8 pvalue) {
654
#define _int32(i) kherr_val(KEPT_INT32, (khm_ui_8) i)
655
#define _uint32(ui) kherr_val(KEPT_UINT32, (khm_ui_8) ui)
656
#define _int64(i) kherr_val(KEPT_INT64, (khm_ui_8) i)
657
#define _uint64(ui) kherr_val(KEPT_UINT64, (khm_ui_8) ui)
658
#define _cstr(cs) kherr_val(KEPT_STRINGC, (khm_ui_8) cs)
659
#define _tstr(ts) kherr_val(KEPT_STRINGT, (khm_ui_8) ts)
660
#define _cptr(p) kherr_val(KEPT_PTR, (khm_ui_8) p)
661
#define _vnull() kherr_val(KEPT_NONE, 0)
662
#define _dupstr(s) kherr_dup_string(s)
664
/* convenience macros for calling kherr_report */
667
#define _report_cs0(severity, long_description) \
668
kherr_report((severity), NULL, KHERR_FACILITY, NULL, (long_description), NULL, KHERR_FACILITY_ID, 0, _vnull(), _vnull(), _vnull(), _vnull(), 0, KHERR_HMODULE)
670
#define _report_cs1(severity, long_description, p1) \
671
kherr_report((severity), NULL, KHERR_FACILITY, NULL, (long_description), NULL, KHERR_FACILITY_ID, 0, p1, _vnull(), _vnull(), _vnull(), 0, KHERR_HMODULE)
673
#define _report_cs2(severity, long_description, p1, p2) \
674
kherr_report((severity), NULL, KHERR_FACILITY, NULL, (long_description), NULL, KHERR_FACILITY_ID, 0, p1, p2, _vnull(), _vnull(), 0, KHERR_HMODULE)
676
#define _report_cs3(severity, long_description, p1, p2, p3) \
677
kherr_report((severity), NULL, KHERR_FACILITY, NULL, (long_description), NULL, KHERR_FACILITY_ID, 0, p1, p2, p3, _vnull(), 0, KHERR_HMODULE)
679
#define _report_cs4(severity, long_description, p1, p2, p3, p4) \
680
kherr_report((severity), NULL, KHERR_FACILITY, NULL, (long_description), NULL, KHERR_FACILITY_ID, 0, p1, p2, p3, p4, 0, KHERR_HMODULE)
684
#define _report_cs0(severity, long_description) \
685
kherr_report((severity), NULL, KHERR_FACILITY, NULL, (long_description), NULL, KHERR_FACILITY_ID, 0, _vnull(), _vnull(), _vnull(), _vnull(), 0, NULL)
687
#define _report_cs1(severity, long_description, p1) \
688
kherr_report((severity), NULL, KHERR_FACILITY, NULL, (long_description), NULL, KHERR_FACILITY_ID, 0, p1, _vnull(), _vnull(), _vnull(), 0, NULL)
690
#define _report_cs2(severity, long_description, p1, p2) \
691
kherr_report((severity), NULL, KHERR_FACILITY, NULL, (long_description), NULL, KHERR_FACILITY_ID, 0, p1, p2, _vnull(), _vnull(), 0, NULL)
693
#define _report_cs3(severity, long_description, p1, p2, p3) \
694
kherr_report((severity), NULL, KHERR_FACILITY, NULL, (long_description), NULL, KHERR_FACILITY_ID, 0, p1, p2, p3, _vnull(), 0, NULL)
696
#define _report_cs4(severity, long_description, p1, p2, p3, p4) \
697
kherr_report((severity), NULL, KHERR_FACILITY, NULL, (long_description), NULL, KHERR_FACILITY_ID, 0, p1, p2, p3, p4, 0, NULL)
698
#endif /* !defined(KHERR_HMODULE) */
701
#define _report_sr0(severity, long_desc_id) \
702
kherr_report((severity), NULL, KHERR_FACILITY, NULL, MAKEINTRESOURCE(long_desc_id), NULL, KHERR_FACILITY_ID, 0, _vnull(), _vnull(), _vnull(), _vnull(), KHERR_RF_RES_LONG_DESC, KHERR_HMODULE)
704
#define _report_sr1(severity, long_desc_id, p1) \
705
kherr_report((severity), NULL, KHERR_FACILITY, NULL, MAKEINTRESOURCE(long_desc_id), NULL, KHERR_FACILITY_ID, 0, p1, _vnull(), _vnull(), _vnull(), KHERR_RF_RES_LONG_DESC, KHERR_HMODULE)
707
#define _report_sr2(severity, long_desc_id, p1, p2) \
708
kherr_report((severity), NULL, KHERR_FACILITY, NULL, MAKEINTRESOURCE(long_desc_id), NULL, KHERR_FACILITY_ID, 0, p1, p2, _vnull(), _vnull(), KHERR_RF_RES_LONG_DESC, KHERR_HMODULE)
710
#define _report_sr3(severity, long_desc_id, p1, p2, p3) \
711
kherr_report((severity), NULL, KHERR_FACILITY, NULL, MAKEINTRESOURCE(long_desc_id), NULL, KHERR_FACILITY_ID, 0, p1, p2, p3, _vnull(), KHERR_RF_RES_LONG_DESC, KHERR_HMODULE)
713
#define _report_sr4(severity, long_desc_id, p1, p2, p3, p4) \
714
kherr_report((severity), NULL, KHERR_FACILITY, NULL, MAKEINTRESOURCE(long_desc_id), NULL, KHERR_FACILITY_ID, 0, p1, p2, p3, p4, KHERR_RF_RES_LONG_DESC, KHERR_HMODULE)
718
#define _report_mr0(severity, long_desc_msg_id) \
719
kherr_report((severity), NULL, KHERR_FACILITY, NULL, (wchar_t *)(long_desc_msg_id), NULL, KHERR_FACILITY_ID, 0, _vnull(), _vnull(), _vnull(), _vnull(), KHERR_RF_MSG_LONG_DESC, KHERR_HMODULE)
721
#define _report_mr1(severity, long_desc_msg_id, p1) \
722
kherr_report((severity), NULL, KHERR_FACILITY, NULL, (wchar_t *)(long_desc_msg_id), NULL, KHERR_FACILITY_ID, 0, p1, _vnull(), _vnull(), _vnull(), KHERR_RF_MSG_LONG_DESC, KHERR_HMODULE)
724
#define _report_mr2(severity, long_desc_msg_id, p1, p2) \
725
kherr_report((severity), NULL, KHERR_FACILITY, NULL, (wchar_t *)(long_desc_msg_id), NULL, KHERR_FACILITY_ID, 0, p1, p2, _vnull(), _vnull(), KHERR_RF_MSG_LONG_DESC, KHERR_HMODULE)
727
#define _report_mr3(severity, long_desc_msg_id, p1, p2, p3) \
728
kherr_report((severity), NULL, KHERR_FACILITY, NULL, (wchar_t *)(long_desc_msg_id), NULL, KHERR_FACILITY_ID, 0, p1, p2, p3, _vnull(), KHERR_RF_MSG_LONG_DESC, KHERR_HMODULE)
730
#define _report_mr4(severity, long_desc_msg_id, p1, p2, p3, p4) \
731
kherr_report((severity), NULL, KHERR_FACILITY, NULL, (wchar_t *)(long_desc_msg_id), NULL, KHERR_FACILITY_ID, 0, p1, p2, p3, p4, KHERR_RF_MSG_LONG_DESC, KHERR_HMODULE)
734
#define _report_ts0(severity, long_desc_ptr) \
735
kherr_report((severity), NULL, KHERR_FACILITY, NULL, (long_desc_ptr), NULL, KHERR_FACILITY_ID, 0, _vnull(), _vnull(), _vnull(), _vnull(), KHERR_RF_FREE_LONG_DESC, NULL)
737
#define _report_ts1(severity, long_desc_ptr, p1) \
738
kherr_report((severity), NULL, KHERR_FACILITY, NULL, (long_desc_ptr), NULL, KHERR_FACILITY_ID, 0, p1, _vnull(), _vnull(), _vnull(), KHERR_RF_FREE_LONG_DESC, NULL)
740
#define _report_ts2(severity, long_desc_ptr, p1, p2) \
741
kherr_report((severity), NULL, KHERR_FACILITY, NULL, (long_desc_ptr), NULL, KHERR_FACILITY_ID, 0, p1, p2, _vnull(), _vnull(), KHERR_RF_FREE_LONG_DESC, NULL)
743
#define _report_ts3(severity, long_desc_ptr, p1, p2, p3) \
744
kherr_report((severity), NULL, KHERR_FACILITY, NULL, (long_desc_ptr), NULL, KHERR_FACILITY_ID, 0, p1, p2, p3, _vnull(), KHERR_RF_FREE_LONG_DESC, NULL)
746
#define _report_ts4(severity, long_desc_ptr, p1, p2, p3, p4) \
747
kherr_report((severity), NULL, KHERR_FACILITY, NULL, (long_desc_ptr), NULL, KHERR_FACILITY_ID, 0, p1, p2, p3, p4, KHERR_RF_FREE_LONG_DESC, NULL)
749
/*! \brief Set the suggestion and suggestion identifier for the last event
751
The event that will be modified is the last event reported by the
754
KHMEXP void KHMAPI kherr_suggest(wchar_t * suggestion, khm_int32 suggestion_id, khm_int32 flags);
755
#define _suggest_cs(cs,sid) kherr_suggest((cs), (sid), KHERR_RF_CSTR_SUGGEST)
756
#define _suggest_ts(ts,sid) kherr_suggest((ts), (sid), KHERR_RF_FREE_SUGGEST)
757
#define _suggest_sr(sr,sid) kherr_suggest(MAKEINTRESOURCE(sr), (sid), KHERR_RF_RES_SUGGEST)
758
#define _suggest_mr(mr,sid) kherr_suggest((wchar_t *)(DWORD_PTR)(mr), (sid), KHERR_RF_MSG_SUGGEST)
760
/*! \brief Set the location string for the last event
762
The event that will be modified is the last event reported by the
765
KHMEXP void KHMAPI kherr_location(wchar_t * location);
766
#define _location(l) kherr_location(l)
768
/*! \brief Set the facility string and identifier for the last event
770
The event that will be modified is the last event reported by the
773
KHMEXP void KHMAPI kherr_facility(wchar_t * facility, khm_int32 facility_id);
774
#define _facility(f,fid) kherr_facility((f),(fid))
776
/*! \brief Marks the last event as the descriptor event for the current error context
778
Note that marking an event as the descriptor event has the effect
779
of removing the event from event queue. The event will henceforth
780
be used as the descriptor for the context. The only effective
781
fields of a descriptor event are \a short_desc, \a long_desc, \a
782
facility, \a facility_id and the parameters which are used for
783
resolving formatted strings in the aforementioned fields.
785
Upon calling kherr_set_desc_event(), the event will be
786
automatically evaluated as if kherr_evaluate_event() was called.
788
The event that will be referenced is the last event reported by
791
KHMEXP void KHMAPI kherr_set_desc_event(void);
792
#define _describe kherr_set_desc_event
794
/*! \brief Delete the last event
796
The event that will be deleted is the last event reported by the
799
KHMEXP void KHMAPI kherr_del_last_event(void);
800
#define _del_event kherr_del_last_event
802
/*! \brief Create a new context
804
The created context is not bound to any thread or any context
805
hierarchy. Hence it cannot be used to capture any events until it
806
is used in a call to kherr_push_context().
808
Release the returned context pointer with a call to
809
kherr_release_context().
811
\param[in] flags Initial flags for the context. Combination of
812
::kherr_context_flags
814
\note This function is for internal use only.
816
KHMEXP kherr_context * KHMAPI kherr_create_new_context(khm_int32 flags);
818
/*! \brief Obtain a hold on a context */
819
KHMEXP void KHMAPI kherr_hold_context(kherr_context * c);
821
/*! \brief Release a context */
822
KHMEXP void KHMAPI kherr_release_context(kherr_context * c);
824
/*! \brief Push an empty context
826
Creates an empty context, adds it as a child of the current
827
thread's error context. If the current thread does not have an
828
error context, then the created error context will be a root level
831
The new context will be the current error context for the calling
834
\param[in] flags Initial flags for the context. Combination of
835
::kherr_context_flags
837
\see kherr_push_new_context() for more information about thread
838
specific context stacks.
841
KHMEXP void KHMAPI kherr_push_new_context(khm_int32 flags);
842
#define _begin_task kherr_push_new_context
844
/*! \brief Push a context
846
Each thread has a stack of error contexts. The topmost one is
847
current. The thread can push or pop contexts on to the stack
848
independently of the hierarchy of contexts (the only exception, as
849
explained below is when the context that is being pushed is
852
If the context being pushed by kherr_push_context() is unbound,
853
then it will be attached to the current context of the thread as a
854
child. Once the new context is pushed to the top of the stack, it
855
will become the current context for the thread.
857
The calling thread must call kherr_pop_context() to remove the
858
context from the top of the stack. Each call to
859
kherr_push_new_context() or kher_push_context() must have a
860
corresponding kherr_pop_context() call.
862
When the thread terminates, all of the contexts in the thread's
863
context stack will be automatically removed.
865
\see kherr_pop_context()
867
KHMEXP void KHMAPI kherr_push_context(kherr_context * c);
869
/*! \brief Pop a context
871
Remove the current error context from the thread's context stack.
872
If no other open handles exist to the error context, this causes
873
the error context to collapse into it's parent context or vanish
874
entirely unless the context contains an error.
876
\see kherr_push_context() for more information about thread
877
specific context stacks.
879
KHMEXP void KHMAPI kherr_pop_context(void);
880
#define _end_task kherr_pop_context
882
/*! \brief Retrieve the current error context
884
The returned pointer must be released with a call to
885
kherr_release_context().
887
KHMEXP kherr_context * KHMAPI kherr_peek_context(void);
889
/*! \brief Check if the current error context indicates an error
891
\return TRUE if there is an error. FALSE otherwise.
894
KHMEXP khm_boolean KHMAPI kherr_is_error(void);
896
/*! \brief Check if an error context indicates an error
898
\return TRUE if there is an error. FALSE otherwise.
901
KHMEXP khm_boolean KHMAPI kherr_is_error_i(kherr_context * c);
903
/*! \brief Clear the error state of the current context */
904
KHMEXP void KHMAPI kherr_clear_error(void);
906
/*! \brief Clear the error state of an error context */
907
KHMEXP void KHMAPI kherr_clear_error_i(kherr_context * c);
909
/*! \brief Set the progress meter of the current error context
911
Setting \a denom to zero removes the progress meter.
913
KHMEXP void KHMAPI kherr_set_progress(khm_ui_4 num, khm_ui_4 denom);
914
#define _progress(num,denom) kherr_set_progress((num),(denom))
916
/*! \brief Get the progress meter of the current error context
918
This is equivalent to calling kherr_get_progress_i() for the
919
current error context. I.e. :
924
ctx = kherr_peek_context();
925
kherr_get_progress_i(ctx, &num, &denom);
926
kherr_release_context(ctx);
929
\see kherr_get_progress_i()
931
KHMEXP void KHMAPI kherr_get_progress(khm_ui_4 * num, khm_ui_4 * denom);
933
/*! \brief Get the progress meter of an error context
935
The progress meter for the current context can be set by calling
936
kherr_set_progress() (or using the ::_progress macro). The
937
progress value returned by this function is as follows:
939
If one or more of the following conditions are true, then the
940
returned progress values are the values set for the context using
941
the most recent call to kherr_set_progress():
943
- if the numerator and the denominator are non-zero
945
- if the ::KHERR_CF_OWN_PROGRESS flag is set for the context.
947
Otherwise, the function will calculate the progress by enumerating
948
all the child context for the context and summing up the
949
normalized numerators and the denominators for them.
951
KHMEXP void KHMAPI kherr_get_progress_i(kherr_context * c, khm_ui_4 * num, khm_ui_4 * denom);
953
/*! \brief Get the first event in a context
955
The returned pointer is only valid as long as there is a hold on
956
\a c. Once the context is released with a call to
957
kherr_release_context() all pointers to events in the context
960
In addition, the last event in a context may still be "active". A
961
thread can still modify the last event as long as the context is
964
\see kherr_get_next_event(), kherr_get_prev_event(),
965
kherr_get_last_event()
967
KHMEXP kherr_event * KHMAPI kherr_get_first_event(kherr_context * c);
969
/*! \brief Get the next event
971
Call kherr_get_first_event() to obtain the first event in a
972
context. Subsequent calls to kherr_get_next_event() will yield
973
other events in the order in which they were reported. The list
974
ends when kherr_get_next_event() returns NULL.
976
The returned pointer is only valid as long as there is a hold on
977
\a c. Once the context is released with a call to
978
kherr_release_context() all pointers to events in the context
981
In addition, the last event in a context may still be "active". A
982
thread can still modify the last event as long as the context is
985
\see kherr_get_first_event(), kherr_get_prev_event(),
986
kherr_get_last_event()
988
KHMEXP kherr_event * KHMAPI kherr_get_next_event(kherr_event * e);
990
/*! \brief Get the previous event
992
Returns a pointer to the event that was reported in the context
993
containing \a e prior to \a e being reported.
995
The returned pointer is only valid as long as there is a hold on
996
the error context. Once the context is released with a call to
997
kherr_release_context() all pointers to events in the context
1000
In addition, the last event in a context may still be "active". A
1001
thread can still modify the last event as long as the context is
1004
\see kherr_get_first_event(), kherr_get_next_event(),
1005
kherr_get_last_event()
1007
KHMEXP kherr_event * KHMAPI kherr_get_prev_event(kherr_event * e);
1009
/*! \brief Get the last event in an error context
1011
Returns a pointer to the last error event that that was reported
1012
to the context \a c.
1014
The returned pointer is only valid as long as there is a hold on
1015
the error context. Once the context is released with a call to
1016
kherr_release_context(), all pointers to events in the context
1019
In addtion, the last event in a context may still be "active". A
1020
thread can still modify the last event as long as the context is
1023
\see kherr_get_first_event(), kherr_get_next_event(),
1024
kherr_get_prev_event()
1026
KHMEXP kherr_event * KHMAPI kherr_get_last_event(kherr_context * c);
1028
/*! \brief Get the first child context of a context
1030
Contexts are arranged in a hiearchy. This function returns the
1031
first child of an error context. Use kherr_get_next_context() to
1032
obtain the other contexts. If \a c is \a NULL, this returns the
1033
first root level context.
1035
The returned pointer must be released with a call to
1036
kherr_release_context()
1038
KHMEXP kherr_context * KHMAPI kherr_get_first_context(kherr_context * c);
1040
/*! \brief Get the next sibling context of a context
1042
The returned pointer must be released with a call to
1043
kherr_release_context()
1045
\see kherr_get_first_context()
1047
KHMEXP kherr_context * KHMAPI kherr_get_next_context(kherr_context * c);
1049
/*! \brief Get the desciption event for the context
1051
The description event is the event that was denoted using
1052
kherr_set_desc_event() as the event which describes the context.
1054
The returned pointer is only valid as long as there is a hold on
1055
\a c. Once the context is released with a call to
1056
kherr_release_context() all pointers to events in the context
1059
KHMEXP kherr_event * KHMAPI kherr_get_desc_event(kherr_context * c);
1061
/*! \brief Get the error event for the context
1063
The error event for a context is the last event that had the
1064
highest severity level.
1066
The returned pointer is only valid as long as there is a hold on
1067
\a c. Once the context is released with a call to
1068
kherr_release_context() all pointers to events in the context
1071
KHMEXP kherr_event * KHMAPI kherr_get_err_event(kherr_context * c);
1073
/*! \brief Evaluate an event
1075
When an event is reported, all the parameters and resource
1076
references that were passed to kherr_report() are kept as-is until
1077
the actual string values are required by the error reporting
1078
library. However, if the string fields are required before then,
1079
an application can call kherr_evaluate_event() to get them.
1081
This function does the following:
1083
- Load any referenced string or message resources that are
1084
referenced in the event's short description, long description or
1087
- Expand any inserts using the parameters that were passed in.
1089
- Free up allocated strings in for the descriptions or suggestion
1090
fields and any parameters.
1092
- Update the string fields in the event to contain the newly
1096
KHMEXP void KHMAPI kherr_evaluate_event(kherr_event * e);
1098
/*! \brief Evaluate the last event
1100
Same as kherr_evaluate_event(), but operates on the last event
1101
logged by the current thread.
1103
\see kherr_evaluate_event()
1105
KHMEXP void KHMAPI kherr_evaluate_last_event(void);
1106
#define _resolve kherr_evaluate_last_event
1108
/*! \defgroup kherr_fids Standard Facility IDs
1110
#define KHM_FACILITY_KMM 1
1111
#define KHM_FACILITY_KCDB 2
1112
#define KHM_FACILITY_UI 3
1113
#define KHM_FACILITY_KRB5 64
1114
#define KHM_FACILITY_KRB4 65
1115
#define KHM_FACILITY_AFS 66
1116
#define KHM_FACILITY_USER 128
1121
/* In debug mode, outputs the formatted string to the debug console */
1123
KHMEXP void kherr_debug_printf(wchar_t * fmt, ...);