Kernel Memory Space Analyzer — Architecture and Interfaces (Phase 3)

 

Last Updated: 12/25/99

 


1.     Architectural Overview.. 3

2.     Data Items and the Type Namespace. 3

3.     Modeling With Base Data Items. 3

3.1               Container/Containee Relationships. 3

3.2               Pointer Relationships. 3

4.     Plug-In Interface. 3

4.1               Loading and Registration. 3

4.2               Interface Routine. 3

4.2.1        KA_INITIALIZE. 3

4.2.2        KA_REGISTER_TYPES. 3

4.2.3        KA_START_LOCATE_ITEMS. 3

4.2.4        KA_PROCESS_ITEM... 3

4.2.5        KA_NOTIFY_ITEM... 3

4.2.6        KA_PERFORM_ANALYSIS. 3

4.2.7        KA_DB_CONNECT. 3

4.2.8        KA_DB_CONTROL. 3

4.2.9        KA_DB_BUILD_QUERY.. 3

4.2.10      KA_DB_PROCESS_CLASS. 3

4.2.11      KA_PROCESS_RESULT. 3

4.2.12      KA_DB_UPDATE. 3

4.2.13      KA_TERMINATE. 3

4.2.14      KA_FORMAT_DATA_ITEM_DESCRIPTION.. 3

4.2.15      KA_PRIVATE. 3

4.3               Helper/Callback Routines. 3

4.3.1        Crash Information Retrieval 3

4.3.2        Symbol Handling and Lookup. 3

4.3.3        Kanalyze Parameter Retrieval 3

4.3.4        Writing to the Log. 3

4.3.5        Verbosity Checking. 3

4.3.6        Checking for Break/Cancel 3

4.3.7        Calling Other Plug-Ins’ Private Interface Routines. 3

4.3.8        Reading “Memory”. 3

4.3.9        “Writing” “Memory”. 3

4.3.10      Reading Processor Context, Control Space. 3

4.3.11      Retrieving a Data Item Type Handle. 3

4.3.12      Retrieving Data Item Type Information. 3

4.3.13      Enumerating Data Item Types. 3

4.3.14      Retrieving Details about a Data Item.. 3

4.3.15      Locating/Enumerating Located Data Items. 3

4.3.16      Enumerating Data Item Links. 3

4.3.17      Retrieving A Data Item’s Type-Specific Data. 3

4.3.18      Retrieving a Human-Readable Description of a Data Item.. 3

4.3.19      Calling a Method Interface Routine. 3

4.3.20      Locating a Published Helper/Callback Table. 3

4.3.21      Broadcasting a Message to All Plug-Ins. 3

5.     Engine Interface. 3

5.1               Initializing the Kanalyze Engine. 3

5.2               Setting and Retrieving Kanalyze Parameters. 3

5.3               Loading and Unloading Crash Dump Files. 3

5.4               Loading and Unloading Symbols. 3

5.5               Loading Plug-Ins. 3

5.6               Known Issues Database Functionality. 3

5.6.1        Connecting and Disconnecting. 3

5.6.2        Querying/Searching. 3

5.6.3        Updating. 3

5.7               Detailed Analysis. 3

5.8               Processing Results. 3

5.9               Shutting Down the Kanalyze Engine. 3

6.     Database Matching and Processing. 3

6.1               Signature Id File. 3

6.2               Building the Database Query. 3

6.3               Processing Query Results (Matching Crash Classes) 3

 


1.      Architectural Overview

Kernel memory space is a vast and overwhelming place. It is not feasible for one program to monolithically encompass all the knowledge required to analyze it. Thus the central design consideration for kanalyze is to allow compartmentalization of the functionality required to perform the analysis. This is accomplished by basing kanalyze’s architecture on a core engine, and an interface for so-called “plug-in” modules, which are closely tied to the various analytically significant data concepts in kernel memory space and the results of analyzing a crash. A natural benefit of this is that the plug-in interface provides an excellent framework for gathering data about a crashed system via a crash dump file. Thus an additional central design consideration is to allow convenient harnessing of such data, which includes any problems found in kernel space during analysis.

 

Following these 2 central design considerations, plug-ins fall loosely into 4 general categories. The boundaries between these categories are conceptual only. The plug-in interface is completely uniform and a given plug-in may include any or all types of functionality.

 

The first two categories represent the data producers, which populate a space represented by a unified name hierarchy with information about analytically significant data items (modules, memory ranges, structures, etc.); anomalies found in such items; and the results of analysis performed. Base plug-ins are responsible for locating and validating the data items. Analysis plug-ins are responsible for performing analysis that goes beyond validating the items.

 

The third general plug-in category is director plug-ins, which are the data consumers. They harness data — especially anomaly and analysis data — supplied by other plug-ins, for such purposes as generating textual output to the user and providing interactive capabilities. UI is director functionality.

 

Finally there is a fourth category, special plug-ins. Special plug-ins are those that do not fit into any of the above categories, such as those that provide services for other plug-ins without identifying any data items, performing any analysis, or providing any UI. This category is useful for tasks such as providing connectivity to the known issues database, etc.

 

The kanalyze engine does not itself identify or analyze any data. All such work is done by plug-ins. Thus kanalyze’s analysis is only as deep as provided by base and analysis plug-ins and its output is only as useful as provided by its director plug-ins. A key feature of kanalyze is that it allows anyone to write plug-ins to adapt its function according to his needs or the needs of his organization.

 

Table of Contents Ý

 

2.      Data Items and the Type Namespace

The fundamental unit of information processed by kanalyze and plug-ins is the data item. Data items have a set of fixed characteristics and a set of type-specific characteristics. Fixed characteristics include the type of the data item, a human-readable description of the data item, pointers to other data items, and the allowed container types for the data item. Type-specific characteristics, on the other hand, are free-form in nature and are not constrained by kanalyze.

 

The concept of a data item is an umbrella unifying several entities:

 

 

Each instance of one of the above is a data item. Base and analysis plug-ins locate/create data items at various points in the flow of a kanalyze invocation and report them to the kanalyze engine. The kanalyze engine maintains a store of reported data items during the lifetime of a kanalyze run. Each data item is of a specific type; each type is handled by a particular plug-in. The types have names and are organized into a unified namespace hierarchy.

 

The root of the hierarchy is simply \. Basic data item types are descendents of \ at arbitrary depth; both leaf and non-leaf nodes in the type hierarchy can be instantiated. For example, a plug-in might register an ObjectTable data item type to correspond to per-process object tables in kernel space. Logical subcomponents of object tables could be type objects, directory objects, and symbolic link objects. Corresponding to this, the data item type namespace would contain \ObjectTable, \ObjectTable\TypeObject, \ObjectTable\DirectoryObject, and \ObjectTable\SymbolicLinkObject, and data items could (and would) exist in the store for all of these 4 types.

 

Levels in the hierarchy are construed based on conceptual groupings, and not necessarily physical container/containee relationships. For example, a type \Pool\NonPaged\UsedBlock might exist to represent non-paged pool blocks. A symbolic link object (as described above) could reside in non-paged pool — but note that \ObjectTable\SymbolicLinkObject is not a descendent of \Pool\NonPaged\UsedBlock in the namespace hierarchy. In other words, the relationships of data items are independent from the relationships of the *types* of data items.

 

Anomaly data items and analysis data items are also part of the data item type namespace, rooted by convention at \Anomaly and \Analysis, respectively. The type of an anomaly data item is by convention the same as the corresponding basic data item, but rooted at \Anomaly. For example, if a plug-in supports data items of type \KernelObject\Thread, then the type for anomalies related to thread data items is \Anomaly\KernelObject\Thread.

 

The kanalyze engine has a set of interfaces to allow plug-ins to do things like enumerate all the data items of a given type. Plug-ins are required to provide interfaces to do things like provide a human-readable description of a given data item. Plug-ins may also provide a set of method interfaces to allow other plug-ins to query type-specific data from individual data items. All of these interfaces are completely orthogonal. This allows, for example, a director plug-in to enumerate all analysis results, request human-readable descriptions for them, and show them to the user. The exact same code could also display a list of all symbolic link objects in the system to the user, simply by changing the name of the data item type used to do the enumeration.

 

The actual namespace used by supplied plug-ins is described in detail in the kanalyze plug-in reference document.

 

Table of Contents Ý

 

3.      Modeling With Base Data Items

Base data items closely correspond to individual objects (structures, modules, memory regions, etc.) in a crashed system. The collection of base data items identified by base plug-ins during a kanalyze run’s lifetime comprises kanalyze’s view of that crashed system. The relationships among entities in the system can be complex. Kanalyze breaks down these relationships into two categories for modeling purposes: container/containee relationships, and pointer relationships.

 

Kanalyze’s analysis flow and the interfaces used by plug-ins follow this data model closely.

 

Table of Contents Ý

 

3.1      Container/Containee Relationships

Container/containee relationships, as the name implies, are those of a base data item containing another base data item. These relationships can have an arbitrary number of levels, for example, a structure within another structure which is within a module’s code area, which is within the module’s address space, etc. In this way the container/containee relationships form a hierarchy. There are several features of the container/containee hierarchy.

 

 

At the top of the base data item container hierarchy is a root container. This diagram shows the immediate descendents of the root in a highly simplified imaginary kernel memory space. The root is labeled as unknown.

 

 

This next diagram shows a few more levels of depth in some areas of the imaginary kernel memory space.

 

 

Note how each base data item fits entirely within some other data item. This diagram also shows some pointer relationships.

 

Table of Contents Ý

 

3.2      Pointer Relationships

Structures within kernel space can point to each other. These relationships are modeled in kanalyze with data item links. Note that this is entirely separate from the container/containee hierarchy. For example, a structure in a linked list has pointers to other structures in the linked list, but the structures in the list are not contained within each other.

 

Base plug-ins can report data items as either sources or targets to indicate pointer relationships. These are tracked and interfaces are provided so that plug-ins can query the linkages. This allows, for example, a director plug-in to determine all the structures (as represented by their data items) that point at a given structure (as represented by its data item).

 

Table of Contents Ý

 

4.      Plug-In Interface

This section describes the programmatic interface used by kanalyze plug-ins, known as the plug-in interface.

 

Kanalyze plug-ins live inside Win32 DLLs; one DLL may contain multiple plug-ins. A plug-in DLL registers each plug-in it contains, supplying the kanalyze engine with an identifier, and the address of a routine via which the engine will communicate with the plug-in — the plug-in’s interface routine. The interface routine is used to request a plug-in to perform various actions relating to analysis. The engine calls the interface routine and examines the return value to determine the result. While a plug-in is processing, it can call helper callback routines. Helper callback routines comprise a sort of kanalyze runtime exported by the kanalyze engine for doing useful things such as retrieving kanalyze command line parameters, accessing the crash dump file, finding data items reported by other plug-ins and matching certain criteria, etc.

 

Table of Contents Ý

 

4.1      Loading and Registration

A plug-in DLL must export a routine with the reserved name KanalyzeRegisterPlugIns. The kanalyze engine does a LoadLibrary followed by a GetProcAddress of this reserved name to load the plug-in DLL and retrieve the address of its registration entry point. The engine then calls the registration entry point, passing the address of a callback function that the DLL must call in order to register each plug-in it contains.

 

The form of the registration entry point which must be exported by a DLL containing kanalyze plug-ins is as follows.

 

VOID
CALLBACK
KanalyzeRegisterPlugIns(
            IN KANALYZE_REGISTER_PLUGIN_PROC RegistrationRoutine,
            IN ULONG32 CrashPlatform,
            IN ULONG32 CrashBuildNumber,
            PVOID Reserved1,
            UINT_PTR Reserved2
            );

 

Parameters:

 

RegistrationRoutine — supplies the address of a routine within the kanalyze engine which the DLL must call to register each plug-in it contains. This routine is documented below.

 

CrashPlatform — supplies a value indicating which type of machine the crash dump is for. This is a value from the IMAGE_FILE_MACHINE_xxx constants in ntimage.h. Valid values are currently 0x14c for 32-bit x86.

 

CrashBuildNumber — supplies the Windows NT build number of the system running on the machine that crashed.

 

Reserved1, Reserved2 — unused at this time; must be 0.

 

The DLL must call RegistrationRoutine for each plug-in it contains. The kanalyze engine assigns each registered plug-in a unique handle, which is used whenever the engine and a plug-in communicate.

 

typedef
HKAPLUGIN
(CALLBACK *KANALYZE_REGISTER_PLUGIN_PROC)(
            IN UINT Version,
            IN LPCWSTR Identifier,
            IN PKANALYZE_INTERFACE_PROC InterfaceRoutine,
            OUT PKANALYZE_EXTENSION_APIS HelperRoutineTable,

            IN PKANALYZE_HELPER_TABLES PrivateHelperTables, OPTIONAL
            UINT_PTR Reserved
            );

 

Parameters:

 

Version — supplies the plug-in interface version with which the plug-in expects to operate. In the future the engine may support mixing of plug-in versions but for now this value must be KANALYZE_INTERFACE_VERSION (currently defined as 3).

 

Identifier — supplies a string identifier by which the plug-in is known. This value must be unique across all plug-ins. If a name collision occurs, the previously registered plug-in with the same Identifier is unloaded by the engine (i.e., the newer one “wins”). This value has a maximum length of  MAX_PLUG_IN_NAME (including the terminating nul).

 

InterfaceRoutine — supplies the address of the interface routine for the plug-in being registered. The DLL is free to have one master interface routine for all plug-ins it contains (using the plug-in handle to distinguish among them); or to have an individual interface routine for each plug-in it contains; or any mixture of these two approaches.

 

PrivateHelperTables — supplies information about private helper/callback routine tables published by this plug-in.

 

HelperRoutineTable — receives a table of pointers to routines "exported" by the kanalyze engine, which are useful to plug-ins. These routines are used for reading from the crash dump file, looking up symbols, locating data items found by other plug-ins, communicating with other plug-ins, etc. For a given Version this table will be the same, so a DLL is free to pass the same value for HelperRoutineTable multiple times when registering multiple plug-ins

 

Reserved — unused at this point; must be 0.

 

Return Value:

 

The return value is an opaque value assigned by the kanalyze engine to the plug-in. This value is unique to one plug-in and is used whenever the engine and plug-ins communicate.

 

Table of Contents Ý

 

4.2      Interface Routine

The kanalyze engine drives the analysis procedure, requesting plug-ins to perform various actions relating to analysis by calling their interface routines. The interface routine is similar to a window procedure in that it is polymorphic; the interpretation of some of the parameters depends on an operation code. When the engine calls a plug-in's interface routine, the plug-in is expected to synchronously perform the requested action and then return a (Win32) error code indicating the outcome. While processing, the plug-in can call appropriate helper/callback routines by using the table it got at registration time. The plug-in can also call whatever Win32 APIs it needs to.

 

typedef
UINT_PTR
(CALLBACK *PKANALYZE_INTERFACE_PROC)(
            IN HKAPLUGIN PlugInHandle,
            IN UINT32 OperationCode,
            IN OUT UINT_PTR Param1,
            IN OUT PVOID Param2
            );

 

Parameters:

 

PlugInHandle — supplies a plug-in's handle, as returned by the registration callback routine at plug-in registration time.

 

OperationCode — supplies a code indicating which action the engine is requesting the plug-in to perform. Kanalyze requires plug-ins to support a set of predefined operation codes. Plug-ins are also free to implement any number of private interfaces. See below.

 

Param1, Param2 — supply OperationCode-dependent parameters.

 

Return Value:

 

The return value is a Win32 error code indicating the outcome of the operation. Note that the return value should indicate errors in processing only. For example if the engine asks a plug-in to process a data item and the plug-in successfully determines that the data item is invalid then the return value should be NO_ERROR to indicate that processing completed successfully; the bogus data item's status is reported via other means. In general, if a plug-in returns a value other than NO_ERROR it will be disabled, meaning that the engine will stop calling its interface routine and it will no longer be participating in the analysis.

 

The value ERROR_INVALID_FUNCTION should be returned if the plug-in does not recognize/support the given OperationCode. If a plug-in returns this value in response to one of the standard interface operation codes, it will be disabled. See preceding discussion.

 

 

The processing performed by a plug-in when its interface routine is called will vary widely depending on OperationCode. The set of standard operations which must be supported by a plug-in are as follows.

 

KA_INITIALIZE — directs a plug-in to initialize

KA_REGISTER_TYPES — directs a plug-in to tell the engine which data item types it supports

KA_START_LOCATE_ITEMS — directs a plug-in to begin locating its data items

KA_PROCESS_ITEM — directs a plug-in to perform additional processing on a data item

KA_NOTIFY_ITEM — notifies a plug-in that a data item of a particular type has been located by a different plug-in

KA_PERFORM_ANALYSIS — directs a plug-in to perform analysis beyond locating and validating data items

KA_DB_CONNECT — directs one plug-in to connect to or disconnect from a known issues database

KA_DB_CONTROL — directs one plug-in to start driving the process of building and executing a known issues database query

KA_DB_BUILD_QUERY — directs a plug-in to describe the crash classes it wants to match in the known issues database

KA_DB_PROCESS_CLASS — directs a plug-in to determine whether a crash class retrieved from the database matches the current crash/sigidfile

KA_PROCESS_RESULT — directs a plug-in to perform any additional processing it wishes to perform

KA_DB_UPDATE — directs one plug-in to update the database

KA_TERMINATE — informs a plug-in that kanalyze is terminating gracefully

KA_FORMAT_DATA_ITEM_DESCRIPTION — requests a plug-in to provide a human-readable description of a particular data item

KA_PRIVATE — codes of this value and higher are reserved for plug-ins to define additional interfaces not covered by the standard ones above

 

The sections that follow describe these in detail.

 

Table of Contents Ý

 

4.2.1    KA_INITIALIZE

KA_INITIALIZE is when plug-ins should perform private initialization steps, such as opening private data files, etc. The kanalyze engine sends a KA_INITIALIZE message to a plug-in shortly after it has been loaded. Initialization is performed in two passes, with KA_INITIALIZE being sent to each plug-in once per pass. When a plug-in receives KA_INITIALIZE for the first time, there will likely be other plug-ins that have not yet completed first-pass initialization. When the second pass occurs, all other plug-ins will have completed at least first-pass initialization.

 

This design is intended to allow plug-ins to have initialization-time dependencies on other plug-ins. For example, a plug-in may provide private interface routines that require some preparation before other plug-ins can call them. The plug-in should do this preparation during first-pass KA_INITIALIZE processing so that the private interfaces are available to other plug-ins during second-pass KA_INITIALIZE processing. Plug-ins should generally not call other plug-ins' private interfaces during the first KA_INITIALIZE pass.

 

For KA_INITIALIZE, the interface routine is used as follows. Note that PlugInInterfaceRoutine is a placeholder for the actual name of the plug-in's interface routine.

 

UINT_PTR
PlugInInterfaceRoutine(
            IN HKAPLUGIN PlugInHandle,
            IN UINT32 OperationCode,
            IN ULONG32 Pass,
            PVOID Unused
            );

 

Parameters:

 

PlugInHandle — supplies the plug-in's handle, as returned by the registration callback routine at plug-in registration time.

 

OperationCode — supplies the value KA_INITIALIZE.

 

Pass (Param1) — supplies the pass, either 0 or 1.

 

Unused (Param2) — unused, will be NULL.

 

Return Value:

 

The return value is a Win32 error code indicating the outcome of the operation. If a plug-in returns a value other then NO_ERROR, then the plug-in is disabled and will not participate in analysis.

 

Table of Contents Ý

 

4.2.2    KA_REGISTER_TYPES

KA_REGISTER_TYPES is used to request that a plug-in inform the engine about the types of data items it supports. For each supported data item type, the plug-in supplies to the engine

 

·          A support level

·          A name and human-readable description

·          A list of allowed container types, which tells the kanalyze engine which data items can legally contain data items of the type being registered

·          Characteristics

·          A method interface routine. Method interfaces provide other plug-ins the ability to retrieve detailed information about particular data items directly from the plug-ins that support them, via a helper/callback routine.

 

One data item type may be supported by multiple plug-ins, at different support levels. This allows plug-ins to aggregate their knowledge about particular data item types. For example, two plug-ins may be able to locate a particular type of data item. One of the plug-ins is the main plug-in for the type and can locate data items in a standalone fashion. The other plug-in is secondary for the data item type and reports data items contained within or pointed to by some other data structure. Another example allows additional plug-ins to add more allowed container types for a given data item type without declaring full support for the type.

 

For KA_REGISTER_TYPES, the interface routine is used as follows. Note that PlugInInterfaceRoutine is a placeholder for the actual name of the plug-in's interface routine.

 

UINT_PTR
PlugInInterfaceRoutine(
            IN HKAPLUGIN PlugInHandle,
            IN UINT32 OperationCode,
            UINT_PTR Unused,
            IN PKANALYZE_REGISTER_TYPES_PROC RegisterTypesCallback
            );

 

Parameters:

 

PlugInHandle — supplies the plug-in's handle, as returned by the registration callback routine at plug-in registration time.

 

OperationCode — supplies the value KA_REGISTER_TYPES.

 

Unused (Param1) — unused; will be 0.

 

RegisterTypesCallback (Param2) — supplies the address of a routine that the plug-in calls to register each data item type it supports. See below.

 

Return Value:

 

The return value is a Win32 error code indicating the outcome of the operation. If a plug-in returns a value other than NO_ERROR, then the plug-in is disabled and will no longer participate in analysis.

 

 

The key feature of the interface routine for KA_REGISTER_TYPES is the RegisterTypesCallback, described here.

 

typedef
UINT32
(CALLBACK *PKANALYZE_REGISTER_TYPES_PROC)(
            IN HKAPLUGIN PlugInHandle,
            IN LPCWSTR TypeName,
            IN LPCWSTR Description,
            IN ULONG32 ContainerTypeCount,
            IN HKATYPE *AllowedContainerTypes,
            IN ULONG32 TypeCharacteristics,
            IN KanalyzeSupportLevel SupportLevel,
            IN PKANALYZE_METHOD_PROC MethodInterface,
            OUT PHKATYPE TypeHandle
            );

 

Parameters:

 

PlugInHandle — supplies the handle of the calling plug-in, as returned at plug-in registration time.

 

TypeName — supplies the name of the data item type. Data item types names are arranged in hierarchical fashion with components separated by path-separator characters (\).

 

Description — supplies a human-readable description of the data item type.

 

ContainerTypeCount — supplies the number of items in the AllowedContainerTypes array.

 

AllowedContainerTypes — supplies a set of handles to previously registered data item types, in which data items of the type being registered may be contained. If the kanalyze engine finds a data item contained in a data item whose type has not been registered as a legal container, an anomaly is reported.

 

TypeCharacteristics — supplies a set of flags that provide additional information about the data item type. These flags may be combined.

 

KA_TC_LOCATE_ALL_ITEMS — this flag indicates that the plug-in is able to definitively locate all the data items of this type. The kanalyze engine uses this flag when checking overlaps.

 

KA_TC_DONT_CHECK_OVERLAP — specifying this flag causes the kanalyze engine to skip checking whether data items of this type are checked for overlap with other data items. Plug-ins should use this flag when registering  abstract data item types such as anomaly data item types.

 

KA_TC_ROOT_ITEM — indicates that data items of this type must be at the root of the data item name hierarchy. If a data item of this type is found and is contained within any other data item, an anomaly is reported. If this flag is not set, and a data item of this type is found at the root, an anomaly is reported.

 

SupportLevel — supplies a value indicating the level of support provided by the plug-in for the data item type.

 

typedef enum {
            SupportAppendContainerTypes = 1,
            SupportDemandNotification = 2,
            SupportSecondary,
            SupportFull
} KanalyzeSupportLevel;

 

SupportAppendContainerTypes — This support level allows the plug-in to declare its knowledge that the data item type can be contained within other data item types. For example, a new plug-in supporting data item types for structures X and Y, both of which contain a nested structure N, would use this support level to inform the engine that N may legally be contained within X and Y data items. For this support level, Description and MethodInterface are ignored.

 

SupportDemandNotification —This support level causes the plug-in to be notified whenever a different plug-in reports a data item of this type. Notification occurs via the KA_NOTIFY_ITEM interface routine. This is especially useful when a plug-in cannot locate its own data items. For example, if a plug-in supports a data item type for structure X, and some of the instances of structure X occur inside of some other structure S supported by a different plug-in, then the plug-in for structure X would register demand notification for structure S data items. At KA_NOTIFY_ITEM time the plug-in would examine the structure S and find its structure X data item. For this support level, Description, ContainerTypeCount, AllowedContainerTypes, and TypeCharacteristics are ignored.

 

SupportSecondary — see SupportFull.

 

SupportFull — This support level indicates that the plug-in is a definitive source for this data item type. This includes the ability to locate, validate, and process these data items, as well as return formatted descriptions of these data items. A plug-in can defer to other plug-ins by using SupportSecondary; in this case if another plug-in registers SupportFull for this data item type then that other plug-in "wins."

 

MethodInterface — supplies the address of a method interface routine for the data item type.

 

TypeHandle — upon success, receives an opaque value assigned by the kanalyze engine to the data type. This value uniquely identifies the data item type for the current invocation of kanalyze.exe.

 

Table of Contents Ý

 

4.2.3    KA_START_LOCATE_ITEMS

KA_START_LOCATE_ITEMS is used to request a plug-in to start locating its base and anomaly data items (but not analysis items, see KA_PERFORM_ANALYSIS). The plug-in should locate each item it can locate by itself, and report it to the engine. A routine is provided to the plug-in by the engine for this purpose. This reporting routine also allows the plug-in to identify other data items to which its data items point. Such “target” data items may be handled by the reporting plug-in or a different plug-in.

 

For KA_START_LOCATE_ITEMS, the interface routine is used as follows. Note that PlugInInterfaceRoutine is a placeholder for the actual name of the plug-in's interface routine.

 

UINT_PTR
PlugInInterfaceRoutine(
            IN HKAPLUGIN PlugInHandle,
            IN UINT32 OperationCode,
            UINT_PTR Unused,
            IN PKANALYZE_LOCATE_PROC LocateItemsCallback
            );

 

Parameters:

 

PlugInHandle — supplies the plug-in's handle, as returned by the registration callback routine at plug-in registration time.

 

OperationCode — supplies the value KA_START_LOCATE_ITEMS.

 

Unused (Param1) — unused, will be 0.

 

LocateItemsCallback (Param2) — supplies the address of a routine which the plug-in calls for each data item it locates.

 

Return Value:

 

The return value is a Win32 error code indicating the outcome of the operation. If a plug-in returns a value other than NO_ERROR, then the plug-in is disabled and will no longer participate in analysis.

 

 

The key feature of the interface routine for KA_START_LOCATE_ITEMS (as well as several others) is the LocateItemsCallback, described here.

 

typedef
UINT32
(CALLBACK *PKANALYZE_LOCATE_PROC)(
            IN HKAPLUGIN PlugInHandle,
            IN KA_ITEM_ID SourceDataItemId, OPTIONAL
            IN PKANALYZE_DATA_ITEM DataItem,
            IN UINT32 Flags,
            OUT PKA_DATA_ITEM_ID DataItemId
            );

 

Parameters:

 

PlugInHandle — supplies the plug-in's handle, as returned by the registration callback routine at plug-in registration time.

 

SourceDataItemId — if specified, indicates that the data item being reported is a link/pointer target and supplies a source data item for a link.

 

DataItem — supplies information that comprises the data item being reported.

 

Flags — supplies a set of values that control and/or modify the behavior of the routine.

 

KA_FLG_IGNORE_TYPE_SPECIFIC_DATA — if this flag is specified and the data item already exists,  then any type-specific data is left alone and not overwritten. Otherwise, the type-specific data of the data item is overwritten with the type-specific data supplied in DataItem.

 

DataItemId — Receives a unique identifier assigned to the data item by the kanalyze engine. This identifier is unique only for the lifetime of the current kanalyze invocation.

 

Return Value:

 

The return value is a Win32 error code indicating the outcome of the operation. If any value other than NO_ERROR is returned by the kanalyze engine, the plug-in should stop processing and return the value it received.

 

Table of Contents Ý

 

4.2.4    KA_PROCESS_ITEM

For KA_PROCESS_ITEM, the interface routine is used as follows. Note that PlugInInterfaceRoutine is a placeholder for the actual name of the plug-in's interface routine.

 

UINT_PTR
PlugInInterfaceRoutine(
            IN HKAPLUGIN PlugInHandle,
            IN UINT32 OperationCode,
            IN KA_ITEM_ID ItemId,
            IN PKANALYZE_LOCATE_PROC LocateItemsCallback
            );

 

Parameters:

 

PlugInHandle — supplies the plug-in's handle, as returned by the registration callback routine at plug-in registration time.

 

OperationCode — supplies the value KA_PROCESS_ITEM.

 

ItemId (Param1) — supplies the data item identifier of a data item previously located and reported to the engine during processing of KA_START_LOCATE_ITEMS or KA_PROCESS_ITEM. The data item may have been reported by a different plug-in than the one being asked to process the item. The engine routes processing for a data item to plug-ins based on the support levels for supported data item types as reported by plug-ins when processing KA_REGISTER_TYPES.

 

LocateItemsCallback (Param2) — supplies the address of a routine which the plug-in calls if it finds any new data items as the result of processing the data item whose Id is given in ItemId.

 

Return Value:

 

The return value is a Win32 error code indicating the outcome of the operation. If a plug-in returns a value other than NO_ERROR, then the plug-in is disabled and will no longer participate in analysis.

 

Table of Contents Ý

 

4.2.5    KA_NOTIFY_ITEM

For KA_NOTIFY_ITEM, the interface routine is used as follows. Note that PlugInInterfaceRoutine is a placeholder for the actual name of the plug-in's interface routine.

 

UINT_PTR
PlugInInterfaceRoutine(
            IN HKAPLUGIN PlugInHandle,
            IN UINT32 OperationCode,
            IN KA_ITEM_ID ItemId,
            IN PKANALYZE_LOCATE_PROC LocateItemsCallback
            );

 

Parameters:

 

PlugInHandle — supplies the plug-in's handle, as returned by the registration callback routine at plug-in registration time.

 

OperationCode — supplies the value KA_NOTIFY_ITEM.

 

ItemId (Param1) — supplies the data item identifier of a data item previously located while a plug-in was processing KA_START_LOCATE_ITEMS, KA_PROCESS_ITEM, or KA_NOTIFY_ITEM.

 

LocateItemsCallback (Param2) — supplies the address of a routine which the plug-in can call to report any additional data items it finds based on data item ItemId.

 

Return Value:

 

The return value is a Win32 error code indicating the outcome of the operation. If a plug-in returns a value other than NO_ERROR, then the plug-in is disabled and will no longer participate in analysis.

 

Table of Contents Ý

 

4.2.6    KA_PERFORM_ANALYSIS

This notification is sent to each plug-in after all (base and anomaly) data items have been located. KA_PERFORM_ANALYSIS directs plug-ins to perform whatever analysis they wish to perform, and report the results in the form of analysis data items. Only data items whose types are in the \Analysis branch of the data item name space hierarchy will be accepted by the engine.

 

Item notification does not function for data items reported during the KA_PERFORM_ANALYSIS phase. Architecturally, a director plug-in should enumerate data items in the \Analysis branch of the data item name space, as opposed to wanting to be notified when analysis items have been reported.

 

When the KA_PERFORM_ANALYSIS phase is complete, all data required for database matching has been added to the signature id file (though the signature id file may not be complete with all the data needed for database updates).

 

For KA_PERFORM_ANALYSIS, the interface routine is used as follows. Note that PlugInInterfaceRoutine is a placeholder for the actual name of the plug-in's interface routine.

 

UINT_PTR
PlugInInterfaceRoutine(
            IN HKAPLUGIN PlugInHandle,
            IN UINT32 OperationCode,
            UINT_PTR Unused,
            IN PKANALYZE_LOCATE_PROC LocateItemsCallback
            );

 

Parameters:

 

PlugInHandle — supplies the plug-in's handle, as returned by the registration callback routine at plug-in registration time.

 

OperationCode — supplies the value KA_PERFORM_ANALYSIS.

 

Unused (Param1) — unused, will be 0.

 

LocateItemsCallback (Param2) — supplies the address of a routine which the plug-in calls to report analysis data items.

 

Return Value:

 

The return value is a Win32 error code indicating the outcome of the operation. If a plug-in returns a value other than NO_ERROR, then the plug-in is disabled and will no longer participate in analysis.

 

Table of Contents Ý

 

4.2.7    KA_DB_CONNECT

The KA_DB_CONNECT notification can be sent at any time after the plug-ins have initialized, to direct a plug-in to connect to a known issues database. Only one plug-in can process this notification; the engine will stop sending KA_DB_CONNECT as soon as one plug-in has indicated that it has been processed (either successfully or unsuccessfully). The connection (or disconnection) must occur synchronously with the notification since the express purpose of KA_DB_CONNECT is to allow direct feedback to a user as to whether the connection parameters supplied to kanalyze are correct. A plug-in that handles this notification must be prepared for multiple retries in case of failure, although the engine will not request multiple simultaneous connections. If the engine requests disconnect, then the plug-in must be able to connect again in the future.

 

For KA_DB_CONNECT, the interface routine is used as follows. Note that PlugInInterfaceRoutine is a placeholder for the actual name of the plug-in's interface routine.

 

UINT_PTR
PlugInInterfaceRoutine(
            IN HKAPLUGIN PlugInHandle,
            IN UINT32 OperationCode,
     IN UINT_PTR ConnectionControl,
      PVOID Unused
      );

 

Parameters:

 

PlugInHandle — supplies the plug-in's handle, as returned by the registration callback routine at plug-in registration time.

 

OperationCode — supplies the value KA_DB_CONNECT.

 

ConnectionControl — supplies a value indicating whether the plug-in is being asked to connect (DBF_CONNECT) or disconnect (DBF_DISCONNECT). If a plug-in receives a ConnectionControl value it does not understand, it must return NO_ERROR.

 

Unused (Param2) — unused; will be NULL.

 

Return Value:

 

The return value is somewhat different than for other KA_xxx cases. If the return value is NO_ERROR, then the engine assumes that the plug-in did not process the KA_DB_CONNECT notification and therefore continues to send this notification to other plug-ins. A return value of -1 indicates that the plug-in successfully processed KA_DB_CONNECT (i.e., is the master known issues database plug-in) and no additional plug-ins will receive KA_DB_CONNECT. Any other Win32 error code indicates that the plug-in is the handler for KA_DB_CONNECT, but was unsuccessful. The plug-in that handles KA_DB_CONNECT must be prepared to retry in this case (i.e., kanalyze might call this plug-in with KA_DB_CONNECT again).

 

Table of Contents Ý

 

4.2.8    KA_DB_CONTROL

This notification is sent to direct a plug-in to build and execute a “pre-query” and then potentially after the KA_PERFORM_ANALYSIS phase has been completed to build and execute the main query. When the engine sends KA_DB_CONTROL, it sends it to each plug-in until one of them indicates that it has processed KA_DB_CONTROL. This limits actual processing of KA_DB_CONTROL to a single plug-in.

 

The plug-in that processes KA_DB_CONTROL is the known issues database “master” plug-in, responsible for building and executing a prequery and also for driving other plug-ins to build the database query to find matching crash classes in the database and then to process the returned classes to see which ones should be reported to the user as matches.

 

In the prequery case, the plug-in independently extracts instance data from the signature id file and then builds and executes a query to determine if the exact crash being examined already exists in the database.

 

In the main query case, processing for KA_DB_CONTROL consists of the following steps:

 

·          Broadcasting KA_DB_BUILD_QUERY to each plug-in to build up the database query

·          Executing the database query to get the matching set of crash classes from the database

·          For each class returned from the query, broadcasting KA_DB_PROCESS_CLASS to each plug-in to determine what level of match the class represents

 

For KA_DB_CONTROL, the interface routine is used as follows. Note that PlugInInterfaceRoutine is a placeholder for the actual name of the plug-in's interface routine.

 

UINT_PTR
PlugInInterfaceRoutine(
            IN HKAPLUGIN PlugInHandle,
            IN UINT32 OperationCode,
            IN UINT_PTR Control,
           
IN PKANALYZE_LOCATE_PROC LocateItemsCallback
            );

 

Parameters:

 

PlugInHandle — supplies the plug-in's handle, as returned by the registration callback routine at plug-in registration time.

 

OperationCode — supplies the value KA_DB_CONTROL.

 

Control — supplies a value indicating which type of query is to be performed. This is one of DBC_DO_PREQUERY or DBC_DO_FULLQUERY. If a plug-in receives a Control value it does not understand, it must return NO_ERROR.

 

LocateItemsCallback (Param2) — supplies the address of a routine which the plug-in calls to report database match data items.

 

Return Value:

 

The return value is somewhat different than for other KA_xxx cases. If the return value is NO_ERROR, then the engine assumes that the plug-in did not process the KA_DB_CONTROL notification and therefore continues to send this notification to other plug-ins. A return value of –1 indicates that the plug-in successfully processed KA_DB_CONTROL (i.e., is the master known issues database plug-in) and no additional plug-ins will receive KA_DB_CONTROL. Any other Win32 error code indicates that the plug-in is the handler for KA_DB_CONTROL, but was unsuccessful. The plug-in that handles KA_DB_CONTROL must be prepared to retry in this case (i.e., kanalyze might call this plug-in with KA_DB_CONTROL again).

 

Table of Contents Ý

 

4.2.9    KA_DB_BUILD_QUERY

The master known issues database plug-in sends KA_DB_BUILD_QUERY to each plug-in to direct it to report the criteria it wants to use to query crash classes from the known issues database. The query criteria are represented by an enumerated type for the item to be matched; an enumerated type for the relationship; and a polymorphic value containing the comparand. A plug-in reports its criteria using a callback routine provided for this purpose. The known issues database plug-in inserts logical ORs between reported criteria.

 

For KA_DB_BUILD_QUERY, the interface routine is used as follows. Note that PlugInInterfaceRoutine is a placeholder for the actual name of the plug-in's interface routine.

 

UINT_PTR
PlugInInterfaceRoutine(
            IN HKAPLUGIN PlugInHandle,
            IN UINT32 OperationCode,
            UINT_PTR Unused,
            IN PKANALYZE_ADD_QUERY_CLAUSES_PROC AddClausesCallback
            );

 

Parameters:

 

PlugInHandle — supplies the plug-in's handle, as returned by the registration callback routine at plug-in registration time.

 

OperationCode — supplies the value KA_DB_BUILD_QUERY.

 

Unused (Param1) — unused, will be 0.

 

AddClausesCallback (Param2) — supplies the address of a routine which the plug-in calls for each query clause set it wants to add to the query string.

 

Return Value:

 

The return value is a Win32 error code indicating the outcome of the operation. If a plug-in returns a value other than NO_ERROR, then the plug-in is disabled and will no longer participate in analysis.

 

A plug-in can call the AddClausesCallback as many times at it wishes. Within a clause set, the individual clauses are ANDed together. For example, plug-in A calls the AddClausesCallback twice, adding the two clause sets

 

     StopCode = a

     StopCodeParam1 = foo!3456

 

and

 

            StopCode = 1e

     StopCodeParam2 = bar!abcd

 

Plug-in B calls the AddClausesCallback once, adding the clause set

 

     StopCode = a

     StopCodeParam1 = foo!564

     StopCodeParam2 = 0

 

In this case the ultimate query will be

 

    ((StopCode = a) AND (StopCodeParam1 = foo!3456))
OR  ((StopCode = 1e) AND (StopCodeParam2 = bar!abcd))
OR  ((StopCode = a) AND (StopCodeParam1 = foo!564) AND (StopCodeParam2 == 0))

 

 

The AddClausesCallback is as follows.

 

typedef
UINT32
(*PKANALYZE_ADD_QUERY_CLAUSES_PROC)(
            IN HKAPLUGIN PlugInHandle,
            IN PKANALYZE_QUERY_CLAUSES Clauses,
            PVOID ReservedMustBe0
            );

 

Parameters:

 

PlugInHandle — supplies the plug-in's handle, as returned by the registration callback routine at plug-in registration time.

 

Clauses — supplies a clause set. Individual clauses within the set are ANDed together. See below for a description of the clause set.

 

ReservedMustBe0 — unused, must be 0 or the routine fails.

 

Return Value:

 

The return value is a Win32 error code indicating the outcome of the operation.

 

 

A structure is used to amalgamate a set of clauses for reporting to the AddClausesCallback callback routine.

 

typedef struct _KANALYZE_QUERY_CLAUSES {
            DWORD Count;
            KANALYZE_QUERY_CLAUSE Clauses[ANYSIZE_ARRAY];
} KANALYZE_QUERY_CLAUSES, *PKANALYZE_QUERY_CLAUSES;

 

Count — supplies the number of clauses in the Clauses array.

 

Clauses — supplies a set of clauses, which are ANDed together.

 

 

An individual clause in a clause set consists of some data, a type for the data, and the relationship of the data to the items in the database for the query.

 

typedef struct _KANALYZE_QUERY_CLAUSE {
            QueryFieldType FieldType;
            QueryOperator Operator;
            ULONG_PTR Value;
} KANALYZE_QUERY_CLAUSE, *PKANALYZE_QUERY_CLAUSE;

 

FieldType — supplies the field to be matched in the query.

 

typedef enum {
            StopCode,                   // Value is a DWORD
            StopParam1,               // Value is an LPCSTR
            StopParam2,               // Value is an LPCSTR
            StopParam3,               // Value is an LPCSTR
            StopParam4,               // Value is an LPCSTR
            NTBuild,                      // Value is a DWORD
            Platform,                     // Value is an LPCSTR
            Keyword1,                   // Value is an LPCSTR
            Keyword2,                   // Value is an LPCSTR
            Keyword3,                   // Value is an LPCSTR
            Keyword4                    // Value is an LPCSTR
} QueryFieldType;

 

Operator — supplies the relationship to be tested in the query.

 

typedef enum {
            Equal,
            NotEqual,
            GreaterThan,
            GreaterThanOrEqual,
            LessThen,
            LessThenOrEqual,
            Contains                      // valid only on strings
} QueryOperator;

 

Value — supplies the data to be used for the query. The type of this data depends on the value of FieldType and is described above.

 

Table of Contents Ý

 

4.2.10                       KA_DB_PROCESS_CLASS

This notification is sent to each plug-in after the database query has been executed and a set of matching classes has been retrieved from the database. Each plug-in is sent KA_DB_PROCESS_CLASS once per class matched with the query and is given the class ID and the class data. The plug-in should make a determination as to whether the given class does in fact represent a match with the current crash (as embodied by the sig id file) and to what extent. If the plug-in determines that the class is a match and should be reported to the user, it calls a given routine to report the match.

 

For KA_DB_PROCESS_CLASS, the interface routine is used as follows. Note that PlugInInterfaceRoutine is a placeholder for the actual name of the plug-in's interface routine.

 

UINT_PTR
PlugInInterfaceRoutine(
            IN HKAPLUGIN PlugInHandle,
            IN UINT32 OperationCode,
            IN PKANALYZE_CRASH_CLASS_DATA ClassData,
            IN PKANALYZE_REPORT_MATCH_PROC ReportMatchCallback
            );

 

Parameters:

 

PlugInHandle — supplies the plug-in's handle, as returned by the registration callback routine at plug-in registration time.

 

OperationCode — supplies the value KA_DB_PROCESS_CLASS.

 

ClassData (Param1) — supplies the crash class from the database which is to be compared against the current crash/sigidfile.

 

ReportMatchCallback (Param2) — supplies a routine which is used by the plug-in to report a match which should be displayed to the user. Plug-ins should use this callback rather than attempting to populate the data item store directly with match data items.

 

Return Value:

 

The return value is a Win32 error code indicating the outcome of the operation. If a plug-in returns a value other than NO_ERROR, then the plug-in is disabled and will no longer participate in analysis.

 

 

A crash class is represented by the following data structure:

typedef struct _KANALYZE_CRASH_CLASS_DATA {
            DWORD StructureVersion;
            DWORD Flags;
            DWORD ClassID;
            DWORD SolutionID;
            DWORD AnalysisID;
            DWORD NTBuild;
            DWORD Platform;
            DWORD InstanceCount;
            DWORD StopCode;
            CanonicalLevel CanonicalizationLevel;
            LPCSTR StopCodeParameters[4];
            LPCSTR KeyWords[4];
            SYSTEMTIME FirstOccurance;
            SYSTEMTIME LastOccurance;        
} KANALYZE_CRASH_CLASS_DATA, *PKANALYZE_CRASH_CLASS_DATA;

 

StructureVersion — supplies a value indicating the version of the structure. Must be KA_CRASHCLASS_VERSION (currently defined as 1).

 

Flags — supplies a set of flags.

KA_CRASHCLASS_CANONICAL — indicates that the StopCodeParameters are in canonical form. Otherwise they are in instance form.

 

ClassID — supplies the identifier for the record in the database.

 

SolutionID — supplies the identifier for the associated solution record in the database.

 

AnalysisID — supplies the identifier for the associated analysis/history record(s) in the database.

 

NTBuild — supplies the NT build number.

 

Platform — supplies the platform type (x86, etc.). A value from ntimage.h.

 

InstanceCount — supplies the number of instances of this crash class currently in the database.

 

StopCode — supplies the stop code.

 

CanonicalizationLevel — a value indicating the degree of canonicalization of the stop code parameters.

 

typedef enum {
            CanonLevelNone = 0,
            CanonLevelInstance = 1,  // same as the stop-code parameters
            CanonLevelLow = 4,
            CanonLevelMedium = 7,
            CanonLevelFull = 10
} CanonicalLevel;

 

StopCodeParameters — supplies the bugcheck parameters. If Flags contains the value KA_CRASHCLASS_CANONICAL, then these values are in a canonical form (such as after having been processed by a stop-code-specific plug-in). Otherwise these values are in instance form.

 

KeyWords — supplies the keyword data as inserted by plug-ins.

 

FirstOccurance —supplies the time when an instance of this crash class was first encountered.

 

LastOccurance — supplies the time when an instance of this crash class was most recently encountered.

 

 

Plug-ins should report matches using the ReportMatchCallback instead of attempting to populate the data item store directly with match data items. This ensures consistency and also saves each plug-in from having to perform additional database querying to retrieve the solution description data from the database.

 

typedef
UINT_PTR
(*PKANALYZE_REPORT_MATCH_PROC)(
            IN HKAPLUGIN PlugInHandle,
            IN PKANALYZE_CRASH_CLASS_DATA ClassData,
            IN LPCWSTR
SolutionTextOverride,
OPTIONAL
            IN MatchConfidenceLevel
MatchLevel,
            UINT_PTR ReservedMustBe0
            );

 

Parameters:

 

PlugInHandle — supplies the plug-in's handle, as returned by the registration callback routine at plug-in registration time.

 

ClassData — supplies the crash class that matched.

 

SolutionTextOverride — if specified, then the solution data associated with the SolutionID member of the ClassData structure is not retrieved from the database and instead the text given here is placed in the match data item. If this parameter is not specified then the solution text is automatically retrieved from the database and placed in the data item for later display to the user.

 

MatchLevel — supplies a value indicating the extent/strength of the match.

typedef  enum {
            MatchNot,                   // for completeness; should not ordinarily be used
            MatchWeak,
            MatchFair,
            MatchGood,
            MatchAbsolute
} MatchConfidenceLevel;

 

Return Value:

 

The return value is a Win32 error code indicating the outcome of the operation.

 

Table of Contents Ý

 

4.2.11                       KA_PROCESS_RESULT

For KA_PROCESS_RESULT, the interface routine is used as follows. Note that PlugInInterfaceRoutine is a placeholder for the actual name of the plug-in's interface routine.

 

UINT_PTR
PlugInInterfaceRoutine(
            IN HKAPLUGIN PlugInHandle,
            IN UINT32 OperationCode,
            UINT_PTR Unused1,
            PVOID Unused2
            );

 

Parameters:

 

PlugInHandle — supplies the plug-in's handle, as returned by the registration callback routine at plug-in registration time.

 

OperationCode — supplies the value KA_PROCESS_RESULT.

 

Unused1 (Param1) — unused; will be 0.

 

Unused2 (Param2) — unused; will be NULL.

 

Return Value:

 

The return value is a Win32 error code indicating the outcome of the operation. If a plug-in returns a value other than NO_ERROR, then the plug-in is disabled and will no longer participate in analysis.

 

Table of Contents Ý

 

4.2.12                       KA_DB_UPDATE

KA_DB_UPDATE is sent when the database should be updated. In general only one plug-in acts on this notification – the same plug-in that processes KA_DB_CONNECT and KA_DB_CONTROL.

 

For KA_DB_UPDATE, the interface routine is used as follows. Note that PlugInInterfaceRoutine is a placeholder for the actual name of the plug-in's interface routine.

 

UINT_PTR
PlugInInterfaceRoutine(
            IN HKAPLUGIN PlugInHandle,
            IN UINT32 OperationCode,
            UINT_PTR Unused1,
            IN PKA_DATABASE_UPDATE_PARAMS DatabaseUpdateParams
            );

 

Parameters:

 

PlugInHandle — supplies the plug-in's handle, as returned by the registration callback routine at plug-in registration time.

 

OperationCode — supplies the value KA_DB_UPDATE.

 

Unused1 (Param1) — unused; will be 0.

 

DatabaseUpdateParams (Param2) — supplies parameters that dictate how the database should be updated. See below.

 

Return Value:

 

The return value is a Win32 error code indicating the outcome of the operation. If a plug-in returns a value other than NO_ERROR, then the plug-in is disabled and will no longer participate in analysis.

 

 

The data structure describing the update that should be made is as follows.

 

typedef struct _KA_DATABASE_UPDATE_PARAMS {
            UINT32 ActionsAndFlags;
            KA_ITEM_ID CrashClass;
} KA_DATABASE_UPDATE_PARAMS, *PKA_DATABASE_UPDATE_PARAMS;

 

ActionsAndFlags — supplies a set of flags indicating the type of update that needs to be performed. These flags may be combined bitwise.

 

KA_DB_CREATE_CLASS — indicates that a new crash class should be created in the database.

 

KA_DB_CREATE_INSTANCE — indicates that a new crash instance should be created in the database. If the KA_DB_CREATE_CLASS flag is set, the instance will become the first instance of a newly created class. If the KA_DB_CREATE_CLASS flag is not set, then the CrashClass field indicates the data item id for the matched crash class to which the instance should be added.

 

CrashClass — if the KA_DB_CREATE_CLASS flag is not set and the KA_DB_CREATE_INSTANCE flag is set, then this field supplies the data item id for the matched crash class to which the instance will be added. In all other cases this value must be 0.

 

Table of Contents Ý

 

4.2.13                       KA_TERMINATE

For KA_TERMINATE, the interface routine is used as follows. Note that PlugInInterfaceRoutine is a placeholder for the actual name of the plug-in's interface routine.

 

UINT_PTR
PlugInInterfaceRoutine(
            IN HKAPLUGIN PlugInHandle,
            IN UINT32 OperationCode,
            UINT_PTR Unused1,
            PVOID Unused2
            );

 

Parameters:

 

PlugInHandle — supplies the plug-in's handle, as returned by the registration callback routine at plug-in registration time.

 

OperationCode — supplies the value KA_TERMINATE.

 

Unused1 (Param1) — unused; will be 0.

 

Unused2 (Param2) — unused; will be NULL.

 

Return Value:

 

The return value is ignored.

 

Table of Contents Ý

 

4.2.14                       KA_FORMAT_DATA_ITEM_DESCRIPTION

For KA_FORMAT_DATA_ITEM_DESCRIPTION, the interface routine is used as follows. Note that PlugInInterfaceRoutine is a placeholder for the actual name of the plug-in's interface routine. The engine calls KA_FORMAT_DATA_ITEM_DESCRIPTION as part of the processing for the format data item description helper/callback routine.

 

UINT_PTR
PlugInInterfaceRoutine(
            IN HKAPLUGIN PlugInHandle,
            IN UINT32 OperationCode,
            IN PKANALYZE_DATA_ITEM_STRING_REQUEST Request,
            OUT SIZE_T *CharsWritten
            );

 

Parameters:

 

PlugInHandle — supplies the plug-in's handle, as returned by the registration callback routine at plug-in registration time.

 

OperationCode — supplies the value KA_FORMAT_DATA_ITEM_DESCRIPTION.

 

Request (Param1) — supplies a data structure containing information about the description being requested from the plug-in and the buffer where the plug-in is to place the formatted description.

 

CharsWritten (Param2) — receives the number of Unicode characters the plug-in wrote into the buffer whose information was passed to the plug-in in the Request parameter, or the number of characters required. In the success case, this does not include the terminating nul. In the non-success case, this includes the terminating nul. This is useful to allow the buffer to be resized.

 

Return Value:

 

The return value is a Win32 error code indicating the outcome of the operation. If the supplied buffer is too small, the plug-in is expected to return ERROR_MORE_DATA and put the number of characters required (including the terminating nul) into CharsWritten. If NO_ERROR is returned the plug-in should put the number of characters written into the supplied buffer, not including the terminating nul, into CharsWritten.

 

Table of Contents Ý

 

4.2.15                       KA_PRIVATE

A private interface corresponds to any interface notification code that is numerically greater than or equal to the constant value KA_PRIVATE. A plug-in is free to expose any number of private interface routines. One plug-in calls another plug-in’s private interface routine by using the call plug-in helper/callback.

 

For KA_PRIVATE, the interface routine is used as follows. Note that PlugInInterfaceRoutine is a placeholder for the actual name of the plug-in's interface routine.

 

UINT_PTR
PlugInInterfaceRoutine(
            IN HKAPLUGIN PlugInHandle,
            IN UINT32 OperationCode,
            IN OUT UINT_PTR Param1,
            IN OUT PVOID Param2
            );

 

Parameters:

 

PlugInHandle — supplies the plug-in's handle, as returned by the registration callback routine at plug-in registration time.

 

OperationCode — supplies a value numerically greater than or equal to KA_PRIVATE.

 

Param1 — supplies private data meaningful to the plug-in supporting the private interface.

 

Param2 — supplies private data meaningful to the plug-in supporting the private interface.

 

Return Value:

 

The return value is defined by the plug-in supporting the private interface.

 

Table of Contents Ý

 

4.3      Helper/Callback Routines

Helper/callback routines are a set of routines exported by the kanalyze engine. They comprise a sort of kanalyze engine runtime API. In addition, a plug-in can publish its own set(s) of helper/callback routines for use by other plug-ins.

 

When a plug-in registers, it receives a structure containing the standard helper/callbacks, i.e., those exported by the kanalyze engine.

 

typedef struct _KANALYZE_EXTENSION_APIS {
            ULONG32 StructureSize;
            KANALYZE_GET_CRASH_INFO_ROUTINE GetCrashInfoRoutine;
            KANALYZE_GET_SYMBOL_ROUTINE GetSymbolRoutine;
            KANALYZE_SYMBOL_TO_ADDRESS_ROUTINE SymbolToAddressRoutine;
            KANALYZE_GET_PARAMETER_ROUTINE GetParameterRoutine;
            KANALYZE_WRITE_TO_LOG_ROUTINE WriteToLogRoutine;
            KANALYZE_CHECK_VERBOSITY_ROUTINE CheckVerbosityRoutine;
            KANALYZE_CALL_PLUGIN_ROUTINE CallPlugInRoutine;
            KANALYZE_CHECK_BREAK_ROUTINE CheckBreakRoutine;
            KANALYZE_READ_MEMORY_ROUTINE ReadMemoryRoutine;
            KANALYZE_WRITE_MEMORY_ROUTINE WriteMemoryRoutine;
            KANALYZE_GET_CONTEXT_ROUTINE GetContextRoutine;
            KANALYZE_READ_CONTROL_SPACE_ROUTINE ReadControlSpaceRoutine;
            KANALYZE_GET_TYPE_HANDLE_ROUTINE GetTypeHandleRoutine;
            KANALYZE_QUERY_TYPE_INFO_ROUTINE QueryTypeInfoRoutine;
            KANALYZE_ENUM_TYPE_INFO_ROUTINE EnumTypeInfoRoutine;
            KANALYZE_QUERY_DATA_ITEM_ROUTINE QueryDataItemRoutine;
            KANALYZE_ENUM_STORED_ITEM_ROUTINE EnumStoredItemRoutine;
            KANALYZE_ENUM_LINK_INFO_ROUTINE EnumLinkInfoRoutine;
                KANALYZE_RETRIEVE_TYPE_SPECIFIC_DATA_ROUTINE RetrieveTypeSpecificDataRoutine;
            KANALYZE_GET_DATA_ITEM_DESCRIPTION GetDataItemDescriptionRoutine;
            KANALYZE_CALL_METHOD_ROUTINE CallMethodRoutine;
           
KANALYZE_WRITE_PHYSICAL_MEMORY_ROUTINE WritePhysicalMemoryRoutine;
            KANALYZE_READ_PHYSICAL_MEMORY_ROUTINE ReadPhysicalMemoryRoutine;
            KANALYZE_GET_HELPER_TABLE_ROUTINE GetHelperTableRoutine;
            KANALYZE_BROADCAST_MESSAGE_ROUTINE BroadcastMessageRoutine;
} KANALYZE_EXTENSION_APIS, *PKANALYZE_EXTENSION_APIS;

 

Table of Contents Ý

 

4.3.1    Crash Information Retrieval

Information about the crash can be retrieved with the get crash info helper/callback routine. The information is taken from the crash dump file or signature id file as appropriate.

 

typedef
UINT32
(CALLBACK *KANALYZE_GET_CRASH_INFO_ROUTINE)(
            IN HKAPLUGIN PlugInHandle,
            OUT PKANALYZE_CRASH_INFO CrashInfo
            );

 

Parameters:

 

PlugInHandle — supplies the calling plug-in's handle, as returned by the registration callback routine at plug-in registration time.

 

CrashInfo — receives information taken from the crash dump or signature id file, as appropriate. The SizeOfStruct member of this structure must be set to sizeof(KANALYZE_CRASH_INFO) before calling this routine. See below.

 

Return Value:

 

The return value is a win32 error code, generally NO_ERROR.
ERROR_INVALID_PARAMETER indicates that the caller did not properly fill in the SizeOfStruct member of CrashInfo before calling this routine.
Any other value indicates a kanalyze engine internal error.

 

 

Information is returned in a kanalyze crash info structure.

 

typedef struct _KANALYZE_CRASH_INFO {
            UINT32 SizeOfStruct;
            ULONG64 Flags;
            SIZE_T BugcheckCode;
            SIZE_T BugcheckParameters[4];
            ULONG32 BuildNumber;
            ULONG32 MachineImageType;
            ULONG32 ProcessorCount;
            ULONG32 CurrentProcessor;
} KANALYZE_CRASH_INFO, *PKANALYZE_CRASH_INFO;

 

SizeOfStruct — before calling, the caller must fill this value in with sizeof(KANALYZE_CRASH_INFO).

 

Flags — receives flags providing various information about the dump.

            KA_CHECKED_BUILD indicates that the crash is for a checked build. If this flag is not set then it’s a free build.

KA_TRIAGE_DUMP indicates that the crash dump file is a minidump. If this flag is not set then it’s a summary or full dump.

 

BugcheckCode — receives the code with which the system bugchecked.

 

BugcheckParameters — receives the 4 code-specific bugcheck parameters.

 

BuildNumber — receives the build number of the system that crashed.

 

MachineImageType — receives a value indicating the platform.

 

            0x14c — 32-bit x86

            Other values are possible (IMAGE_FILE_MACHINE_xxx from ntimage.h)

 

ProcessorCount — receives the count of processors on the machine that crashed.

 

CurrentProcessor — receives the 0-based index of the processor that was current when the system crashed.

 

Table of Contents Ý

 

4.3.2    Symbol Handling and Lookup

The symbolic representation of an address can be determined with the get symbol helper/callback routine. An address is thereby looked up and resolved into a symbol and offset.

 

typedef
UINT32
(CALLBACK *KANALYZE_GET_SYMBOL_ROUTINE)(
            IN HKAPLUGIN PlugInHandle,
            IN SIZE_T Address,
            OUT LPWSTR SymbolName,
            IN ULONG32 SymbolBufferSize,
            OUT SSIZE_T *Offset
            );

 

Parameters:

 

PlugInHandle — supplies the calling plug-in's handle, as returned by the registration callback routine at plug-in registration time.

 

Address — supplies the address whose symbol is to be returned.

 

SymbolName — points to a buffer that will receive the name of the symbol.

 

SymbolBufferSize — supplies the size of the buffer pointed to by SymbolName, in units of unicode characters.

 

Offset — receives the offset of the given Address from the address represented by the returned symbol.

 

Return Value:

 

The return value is a win32 error code.
ERROR_FILE_NOT_FOUND indicates that no matching symbol could be found.

 

 

The value of a symbol can be determined with the symbol to address helper/callback routine. A symbol is thereby resolved to an address.

 

typedef
SIZE_T
(CALLBACK *KANALYZE_SYMBOL_TO_ADDRESS_ROUTINE)(
            IN HKAPLUGIN PlugInHandle,
            IN LPCWSTR SymbolName
            );

 

Parameters:

 

PlugInHandle — supplies the calling plug-in's handle, as returned by the registration callback routine at plug-in registration time.

 

SymbolName — supplies the name of the symbol to be resolved. This can be in the “standard” debugger forms, i.e., module!symbolname or just symbolname.

 

Return Value:

 

The return value is the address represented by the symbol, or 0 if the symbol does not exist, etc.

 

Table of Contents Ý

 

4.3.3    Kanalyze Parameter Retrieval

A plug-in can retrieve parameters specified in the kanalyze parameters .ini file (or set into the parameters store during operation) with the get parameter helper/callback routine. The use and storage of parameters is described here.

 

typedef
INT32
(CALLBACK *KANALYZE_GET_PARAMETER_ROUTINE)(
            IN HKAPLUGIN PlugInHandle,
            IN LPCWSTR ParameterName,
            IN UINT_PTR AdditionalInfo,
            OUT PVOID Buffer,
            IN UINT32 BufferSize
            );

 

Parameters:

 

PlugInHandle — supplies the calling plug-in's handle, as returned by the registration callback routine at plug-in registration time.

 

ParameterName — supplies the name of the parameter. This can be an arbitrary string or a reserved value. Reserved values are used to retrieve “well-known” parameters. See the discussion about kanalyze parameters for more information about the parameters .ini file.

 

KAPARAM_DEFAULT_BINARY_PATH — retrieves the *= line from the [binaries] section.

KAPARAM_BINARY_SPEC_COUNT — retrieves the number of lines in the [binaries] section.

KAPARAM_BINARY_SPEC_NAME — retrieves the left hand side of the nth line in the [binaries] section. AdditionalInfo supplies n in this case.

KAPARAM_BINARY_SPEC_PATH — retrieves the right hand side of the nth line in the [binaries] section. AdditionalInfo supplies n in this case.

KAPARAM_DEFAULT_SYMBOL_PATH — retrieves the *= line from the [symbols] section.

KAPARAM_SYMBOL_SPEC_PATH — retrieves the right hand side of the nth line in the [symbols] section. AdditionalInfo supplies n in this case.

KAPARAM_SIGNATURE_ID_FILE_PATH — retrieves the signature id file specification, which is the right hand side of the “signature id file =” line in the global section (i.e., [kanalyze]).

 

If ParameterName is not one of the above, then it supplies a left hand side to be matched, within the section named by AdditionalInfo.

 

If not specified, then all left hand side values are returned, within either the section named by AdditionalInfo if AdditionalInfo is specified, or if not, then within the section whose name matches the calling plug-ins identifier (as specified at plug-in registration time).

 

AdditionalInfo — supplies additional selection criteria for the parameter retrieval. For the reserved values, see the list above with the ParameterName parameter. For non-reserved values, this supplies the section name in the .ini file, and ParameterName supplies the left hand side of the line to search for.

 

Buffer — points to a buffer that receives the data returned. See below.

 

BufferSize — supplies the size of the buffer pointed to by Buffer, in units of unicode characters.

 

Return Value:

 

0 — the supplied buffer is too small to hold the data to be returned, or there are no values in the [binaries] section (when ParameterName is KAPARAM_BINARY_SPEC_COUNT), or there are no lines in the requested section or the section does not exist (when ParameterName is not specified).

-1 — a non-reserved ParameterName was specified and an integer value was found in the parameters file. In this case Buffer is treated as a pointer to a SIZE_T value, and the value of the parameter is placed there.

Other values — indicates the number of unicode characters returned in Buffer, not including the terminating nul. If this value is greater than or equal to BufferSize then the buffer was not large enough and no data was returned in Buffer.

 

Table of Contents Ý

 

4.3.4    Writing to the Log

Kanalyze can maintain a log as it runs, depending on user preference. Plug-ins should log interesting events over the course of their operation, which can be anything and everything from detailed trace and debug information, to fatal errors.

 

typedef
UINT32
(CALLBACK *KANALYZE_WRITE_TO_LOG_ROUTINE)(
            IN HKAPLUGIN PlugInHandle,
            IN KanalyzeLogLevel LogLevel,
            IN BOOL Reserved,
            IN LPCWSTR FormatString, OPTIONAL
            IN UINT32 MessageId, OPTIONAL
            IN va_list *arglist  OPTIONAL
            );

 

Parameters:

 

PlugInHandle — supplies the calling plug-in's handle, as returned by the registration callback routine at plug-in registration time.

 

LogLevel — supplies the detail level of the information being logged. If the detail level exceeds the current logging verbosity level, then the data is quietly filtered out (i.e., not logged).

 

typedef enum {
            LogFatalErrors,
            LogErrors,
            LogWarnings,
            LogInformation,
            LogDetailedInformation
} KanalyzeLogLevel;

 

Note that fatal errors and errors (LogFatalErrors, LogErrors) are passed to the registered UI stream handler for immediate output, as well as logged.

 

Reserved — must be 0.

 

FormatString — if specified, supplies a printf-style format string; arglist supplies the printf arguments. One of FormatString or MessageId must be supplied.

 

MessageId — if FormatString is not specified, this parameter supplies the message table identifier of a message; arglist supplies the FormatMessage insertion strings. Ignored if FormatString is specified. The message is taken from the plug-in’s module (DLL).

 

arglist — supplies printf arguments or FormatMessage insertion strings, depending on whether FormatString or MessageId was specified.

 

Return Value:

 

The return value is a win32 error code, generally NO_ERROR.

 

Table of Contents Ý

 

4.3.5    Verbosity Checking

Before outputting messages (via the UI stream helper/callback table), a plug-in should check the user-selected verbosity level. This can be done with the check verbosity level helper/callback routine.

 

typedef
BOOL
(CALLBACK *KANALYZE_CHECK_VERBOSITY_ROUTINE)(
            IN HKAPLUGIN PlugInHandle,
            IN KanalyzeMessageDetailLevel DetailLevel,
            BOOL Reserved1,
            PVOID Reserved2
            );

 

Parameters:

 

PlugInHandle — supplies the calling plug-in's handle, as returned by the registration callback routine at plug-in registration time.

 

DetailLevel — supplies the detail level of the message the plug-in intends to output. This is checked against the current kanalyze verbosity level to determine if the message should actually be output.

 

typedef enum {
            BasicMessage,
            ExpandedMessage,
            DetailedMessage
} KanalyzeMessageDetailLevel;

 

Reserved1 — must be 0

 

Reserved2 — must be 0

 

Return Value:

 

The return value is 0 if the plug-in should skip outputting the message because it is too detailed based on the current kanalyze verbosity level.

The return value is non-0 if the plug-in should go ahead and output the message.

 

Table of Contents Ý

 

4.3.6     Checking for Break/Cancel

If a plug-in performs a lengthy operation, it should periodically check whether for a break condition, which occurs, for example, if the user cancels kanalyze. The check is performed by calling the check break helper/callback routine.

 

typedef
BOOL
(CALLBACK *KANALYZE_CHECK_BREAK_ROUTINE)(
            IN HKAPLUGIN PlugInHandle,
            IN UINT_PTR Reserved
            );

 

Parameters:

 

PlugInHandle — supplies the calling plug-in's handle, as returned by the registration callback routine at plug-in registration time.

 

Reserved — must be 0.

 

Return Value:

 

The return value is non-0 if the plug-in should abort (and return ERROR_CANCELED).
The return value is 0 if no break condition exists and the plug-in should continue its current processing.

 

Table of Contents Ý

 

4.3.7    Calling Other Plug-Ins’ Private Interface Routines

A plug-in can call another plug-in’s private interface routine with the call plugin helper/callback routine.

 

typedef
UINT32
(CALLBACK *KANALYZE_CALL_PLUGIN_ROUTINE)(
            IN HKAPLUGIN PlugInHandle,
            IN LPCWSTR PlugInName,
            IN UINT32 PrivateOperationCode,
            IN OUT UINT_PTR Param1,
            IN OUT UINT_PTR Param2,
            OUT PBOOL ReachedPlugIn OPTIONAL
            );

 

Parameters:

 

PlugInHandle — supplies the calling plug-in's handle, as returned by the registration callback routine at plug-in registration time.

 

PlugInName — supplies the name (identifier) of the target plug-in, to be called. If this value starts with ^HANDLE= then the remainder is the base-10 ASCII representation of the target plug-in’s handle, instead of the identifier.

 

PrivateOperationCode — supplies the operation code of the interface routine to be called. This value is meaningful only to the target plug-in and is not specified or interpreted by kanalyze itself.

 

Param1, Param2 — supply the 2 interface routine parameters to be passed to the target plug-in.

 

ReachedPlugIn — if specified, receives a Boolean value indicating whether the target plug-in actually existed and was successfully called.

 

Return Value:

 

The return value is whatever is returned by the target plug-in, or ERROR_FILE_NOT_FOUND if the target plug-in specified by PlugInName could not be located. ReachedPlugIn is useful to distinguish these cases.

 

Table of Contents Ý

 

4.3.8    Reading “Memory”

A plug-in can read from a crash dump file, either by virtual address or physical address.

 

typedef
UINT32
(CALLBACK *KANALYZE_READ_MEMORY_ROUTINE)(
            IN HKAPLUGIN PlugInHandle,
            IN PVOID Reserved,
            IN SIZE_T Address,
            OUT PVOID Buffer,
            IN ULONG32 ByteCount,
            OUT PULONG32 BytesRead
            );

 

Parameters:

 

PlugInHandle — supplies the calling plug-in's handle, as returned by the registration callback routine at plug-in registration time.

 

Reserved — must be 0.

 

Address — supplies the virtual address in kernel memory space of the memory area to be read.

 

Buffer — supplies a pointer to a buffer into which the read data will be placed.

 

ByteCount — supplies the number of bytes to read.

 

BytesRead — receives the number of bytes read and copied into Buffer. If the routine is successful, this will always be equal to ByteCount.

 

Return Value:

 

NO_ERROR — the memory was successfully read, and placed into Buffer.
ERROR_READ_FAULT — some error prevented the data from being retrieved from the dump file, for example, Address was invalid.

 

 

typedef
UINT32
(CALLBACK *KANALYZE_READ_PHYSICAL_MEMORY_ROUTINE)(
            IN HKAPLUGIN PlugInHandle,
            IN PVOID Reserved,
            IN SIZE_T PhysicalAddress,
            OUT PVOID Buffer,
            IN ULONG32 ByteCount,
            OUT PULONG32 BytesRead
            );

 

Parameters:

 

PlugInHandle — supplies the calling plug-in's handle, as returned by the registration callback routine at plug-in registration time.

 

Reserved — must be 0.

 

PhysicalAddress — supplies the physical address of the memory area to be read.

 

Buffer — supplies a pointer to a buffer into which the read data will be placed.

 

ByteCount — supplies the number of bytes to read.

 

BytesRead — receives the number of bytes read and copied into Buffer. If the routine is successful, this will always be equal to ByteCount.

 

Return Value:

 

NO_ERROR — the memory was successfully read, and placed into Buffer.
ERROR_READ_FAULT — some error prevented the data from being retrieved from the dump file, for example, PhysicalAddress was invalid or the dump file is a minidump.

 

Table of Contents Ý

 

4.3.9    “Writing” “Memory”

A plug-in can write to the memory space represented by a crash dump file, either by virtual address or physical address. The write does not actually modify the on-disk dump file; the data written exists as written only for the lifetime of the current kanalyze invocation.

 

typedef
UINT32
(CALLBACK *KANALYZE_WRITE_MEMORY_ROUTINE)(
            IN HKAPLUGIN PlugInHandle,
            IN PVOID Reserved,
            IN SIZE_T Address,
            IN CONST VOID *Buffer,
            IN ULONG32 ByteCount,
            OUT PULONG32 BytesWritten
            );

 

Parameters:

 

PlugInHandle — supplies the calling plug-in's handle, as returned by the registration callback routine at plug-in registration time.

 

Reserved — must be 0.

 

Address — supplies the virtual address in kernel memory space of the memory area to be written.

 

Buffer — supplies a pointer to a buffer containing the data to be written.

 

ByteCount — supplies the number of bytes to write.

 

BytesWritten — receives the number of bytes read from Buffer and “written” into the dump. If the routine is successful, this will always be equal to ByteCount.

 

Return Value:

 

NO_ERROR — the memory was successfully written.
ERROR_WRITE_FAULT — some error prevented the data from being written, for example, Address was invalid.

 

 

typedef
UINT32
(CALLBACK *KANALYZE_WRITE_PHYSICAL_MEMORY_ROUTINE)(
            IN HKAPLUGIN PlugInHandle,
            IN PVOID Reserved,
            IN SIZE_T PhysicalAddress,
            IN CONST VOID *Buffer,
            IN ULONG32 ByteCount,
            OUT PULONG32 BytesWritten
            );

 

Parameters:

 

PlugInHandle — supplies the calling plug-in's handle, as returned by the registration callback routine at plug-in registration time.

 

Reserved — must be 0.

 

PhysicalAddress — supplies the physical address of the memory area to be written.

 

Buffer — supplies a pointer to a buffer containing the data to be written.

 

ByteCount — supplies the number of bytes to write.

 

BytesWritten — receives the number of bytes read from Buffer and “written” into the dump. If the routine is successful, this will always be equal to ByteCount.

 

Return Value:

 

NO_ERROR — the memory was successfully written.
ERROR_WRITE_FAULT — some error prevented the data from being written, for example, PhysicalAddress was invalid.

 

Table of Contents Ý

 

4.3.10                       Reading Processor Context, Control Space

A processor context can be retrieved from the dump file with the get context routine.

 

typedef
UINT32
(CALLBACK *KANALYZE_GET_CONTEXT_ROUTINE)(
            IN HKAPLUGIN PlugInHandle,
            IN UINT_PTR Reserved,
            IN UINT32 Processor,
            OUT PCONTEXT Context
            );

 

Parameters:

 

PlugInHandle — supplies the calling plug-in's handle, as returned by the registration callback routine at plug-in registration time.

 

Reserved — must be 0.

 

Processor — supplies the 0-based index of the processor whose context is to be retrieved. The legal range of this value is 0 to n-1, where n is the processor count, such as returned from the get crash info helper/callback routine.

 

Context — receives the context structure for the specified Processor.

 

Return Value:

 

NO_ERROR — the context was successfully retrieved and placed into Context.
ERROR_READ_FAULT — some error prevented the context from being retrieved.

 

 

A control space can be read using the read control space helper/callback routine. The ability to read a control space is a feature of the underlying crashlib; the meaning of a control space is highly processor-specific. For 32-bit x86 and ia64, this routine can be used to read a block of registers from a processor’s context structure. Because the contexts are also available using the get context routine described above, it is unclear how useful the read control space helper/callback is.

 

typedef
BOOL
(CALLBACK *KANALYZE_READ_CONTROL_SPACE_ROUTINE)(
            IN HKAPLUGIN PlugInHandle,
            IN PVOID Reserved,
            IN USHORT Processor,
            IN SIZE_T TargetBaseAddress,
            OUT PVOID UserInterfaceBuffer,
            IN ULONG32 ByteCount,
            OUT PULONG32 BytesRead
            );

 

Parameters:

 

PlugInHandle — supplies the calling plug-in's handle, as returned by the registration callback routine at plug-in registration time.

 

Reserved — must be 0.

 

Processor — supplies the 0-based index of the processor whose control space is to be read. The legal range of this value is 0 to n-1, where n is the processor count, such as returned from the get crash info helper/callback routine.

 

TargetBaseAddress — supplies the address or other specification of the control space to be read. For 32-bit x86 and ia64, this value is the offset within the CONTEXT structure (within the PRCB) for the specified Processor where reading is to begin.

 

UserInterfaceBuffer — supplies a pointer to a buffer into which the read data will be placed.

 

ByteCount — supplies the number of bytes to read.

 

BytesRead — receives the number of bytes read and copied into Buffer. If the routine is successful, this will always be equal to ByteCount.

 

Return Value:

 

NO_ERROR — the control space was successfully read, and placed into UserInterfaceBuffer.
ERROR_READ_FAULT — some error prevented the control space data from being retrieved from the dump file.

 

Table of Contents Ý

 

4.3.11                       Retrieving a Data Item Type Handle

A plug-in can retrieve the data item type handle corresponding to a data item type name using the get type handle helper/callback routine. The handle is needed to retrieve data item type information using the query type info helper/callback routine.

 

typedef
HKATYPE
(CALLBACK *KANALYZE_GET_TYPE_HANDLE_ROUTINE)(
            IN HKAPLUGIN PlugInHandle,
            IN LPCWSTR TypeName
            );

 

Parameters:

 

PlugInHandle — supplies the calling plug-in's handle, as returned by the registration callback routine at plug-in registration time.

 

TypeName — supplies a type name. The type must have been registered by some plug-in during processinf of KA_REGISTER_TYPES.

 

Return Value:

 

The return value is a handle to the names type, or NULL if the named type specified by TypeName could not be located.

 

Table of Contents Ý

 

4.3.12                       Retrieving Data Item Type Information

A plug-in can retrieve information about a data item type using the query type info helper/callback routine.

 

typedef
UINT32
(CALLBACK *KANALYZE_QUERY_TYPE_INFO_ROUTINE)(
            IN HKAPLUGIN PlugInHandle,
            IN HKATYPE TypeHandle,
            IN UINT_PTR Unused,
            OUT PKA_TYPE_INFO TypeInfo
            );

           

Parameters:

 

PlugInHandle — supplies the calling plug-in's handle, as returned by the registration callback routine at plug-in registration time.

 

TypeHandle — supplies the handle of the type about which information is to be returned. This handle is returned to the plug-in that registered the type during processing of KA_REGISTER_TYPES; handles to types registered by other plug-ins can be retrieved using the get type handle helper/callback routine. Handles are also available by enumerating data item types using the enum data item type info helper/callback routine.

 

Unused — unused and must be 0.

 

TypeInfo — receives information about the type referenced by TypeHandle.

 

Return Value:

 

The return value is a win32 error code, which will be NO_ERROR unless TypeHandle is invalid, in which case the return value is ERROR_INVALID_HANDLE.

 

 

Information about a type is returned in the following structure.

 

typedef struct _KA_TYPE_INFO {
            ULONG32 TypeCharacteristics;
            WCHAR TypeName[MAX_TYPE_NAME];
            WCHAR Description[MAX_TYPE_DESC];
            WCHAR SupportPlugInName[MAX_PLUG_IN_NAME];
            ULONG32 ContainerTypeCount;
            HKATYPE AllowedContainerType[MAX_CONTAINER_TYPES];
} KA_TYPE_INFO, *PKA_TYPE_INFO;

 

TypeCharacteristics — a set of flags that describe certain attributes of the type. These are the same flags used when the type was registered during processing of KA_REGISTER_TYPES.

 

TypeName — the name of the type, as specified when the type was registered during processing of KA_REGISTER_TYPES.

 

Description — a human-readable description for the type, as specified when the type was registered during processing of KA_REGISTER_TYPES.

 

SupportPlugInName — the name (identifier) of the plug-in that supports this type.

 

ContainerTypeCount — supplies the number of elements in the AllowedContainerType array that are in use.

 

AllowedContainerType — this array contains a list of the data item types that are allowable containers for this type. A data item of this type can legally be contained only within data items of types listed in this array. This information was specified when the type was registered during processing of KA_REGISTER_TYPES.

 

Table of Contents Ý

 

4.3.13                       Enumerating Data Item Types

A plug-in can enumerate data item types that match certain criteria, using the enum type info helper/callback routine.

 

typedef
UINT32
(CALLBACK *KANALYZE_ENUM_TYPE_INFO_ROUTINE)(
            IN HKAPLUGIN PlugInHandle,
            IN LPCWSTR TypeSpecification,
            IN UINT_PTR Spare1,
            IN UINT_PTR Spare2,
            IN PKANALYZE_ENUM_TYPE_INFO_CALLBACK Callback,
            IN OUT PVOID Context
            );

 

Parameters:

 

PlugInHandle — supplies the calling plug-in's handle, as returned by the registration callback routine at plug-in registration time.

 

TypeSpecification — supplies the prefix of the types to be matched. For example, \foo\bar matches \foo\bar, \foo\barx, \foo\bar\baz, etc. Matching is case-insensitive. If TypeSpecification has a trailing * character, it is stripped off. If not specified or empty, all types are matched.

 

Spare1, Spare2 — unused and must be 0.

 

Callback — supplies the address of a callback routine, which will be called once for each data item type that matches the criteria specified by TypeSpecification. The callback routine is described more fully below.

 

Context — supplies a value meaningful to the caller, which is passed through unchanged to the Callback routine.

 

Return Value:

 

The return value is NO_ERROR if all matching types (including the case where 0 types match) are successfully enumerated. If the Callback routine is called and at any point returns a value other than NO_ERROR, enumeration aborts and the error value returned by the Callback routine is returned.

 

 

The callback routine called by the enum types info helper/callback is as follows.

 

typedef
UINT32
(CALLBACK *PKANALYZE_ENUM_TYPE_INFO_CALLBACK)(
            IN HKAPLUGIN PlugInHandle,
            IN HKATYPE TypeHandle,
            IN OUT PVOID Context
            );

 

Parameters:

 

PlugInHandle — supplies the calling plug-in's handle, as returned by the registration callback routine at plug-in registration time.

 

TypeHandle — supplies a handle for the type that matched. The plug-in can use the query type info helper/callback to retrieve information about the type.

 

Context — supplies the value passed as the Context parameter to the helper/callback.

 

Return Value:

 

The return value is a win32 error code. If other than NO_ERROR, enumeration aborts and the helper/callback routine returns the value returned.

 

Table of Contents Ý

 

4.3.14                       Retrieving Details about a Data Item

A plug-in can retrieve information about a particular data item using the query data item helper/callback routine. Data items are referenced by identifier. Such identifiers are returned, for example, when data items are enumerated using the enum data item helper/callback.

 

typedef
UINT32
(CALLBACK *KANALYZE_QUERY_DATA_ITEM_ROUTINE)(
            IN HKAPLUGIN PlugInHandle,
            IN KA_ITEM_ID DataItemId,
            IN UINT_PTR Unused,
            OUT PKA_DATA_ITEM_INFO DataItemInfo
            );

 

Parameters:

 

PlugInHandle — supplies the calling plug-in's handle, as returned by the registration callback routine at plug-in registration time.

 

DataItemId — supplies the identifier for the data item about which information is to be returned.

 

Unused — unused and must be 0.

 

DataItemInfo — receives information about the data item whose identifier is given by DataItemId.

 

Return Value:

 

The return value is a win32 error code, which will be NO_ERROR unless DataItemId is invalid.

 

 

Information about a data item is returned in the following structure.

 

typedef struct _KA_DATA_ITEM_INFO {
            HKATYPE TypeHandle;
            UINT_PTR Address;
            SIZE_T Size;
            UINT_PTR TypeSpecificParam;
            SIZE_T TypeSpecificDataSize;
            WCHAR ReportedPlugInName[MAX_PLUG_IN_NAME];
} KA_DATA_ITEM_INFO, *PKA_DATA_ITEM_INFO;

 

TypeHandle — represents the type of the data item.

 

Address — the address in kernel space where the data item exists. This can be 0 in some cases, such as for abstract data items (i.e., analysis data items, etc).

 

Size — the size of the data item. This can be 0 in some cases similarly to Address.

 

TypeSpecificParam — each data item type can have type-specific information associated with it. At the discretion of the plug-in, this information can be either scalar in nature or can be a block of data external to the data item itself, if to large to fit into a UINT_PTR.

 

TypeSpecificDataSize — if type-specific data for data items of this type is large enough and at the discretion of the plug-in that supports data items of this type, this member indicates the size of type-specific data for data items of this type. If 0, then there is no external-form type-specific data for data items of this type. Note that type-specific data in external form can be retrieved using the retrieve type-specific data helper/callback routine.

 

ReportedPlugInName — the name (identifier) of the plug-in that reported this data item.

 

Table of Contents Ý

 

4.3.15                       Locating/Enumerating Located Data Items

A plug-in can enumerate data items matching certain criteria using the enum stored item helper/callback routine. Data item identifiers of matching data items are passed to a callback routine.

 

typedef
UINT32
(CALLBACK *KANALYZE_ENUM_STORED_ITEM_ROUTINE)(
            IN HKAPLUGIN PlugInHandle,
            IN PKA_ENUM_STORED_ITEM_SPECIFICATION DataItemSpecification,
            IN UINT_PTR Spare1,
            IN UINT_PTR Spare2,
            IN PKANALYZE_ENUM_STORED_ITEM_CALLBACK Callback,
            IN OUT PVOID Context
            );

 

Parameters:

 

PlugInHandle — supplies the calling plug-in's handle, as returned by the registration callback routine at plug-in registration time.

 

DataItemSpecification — supplies the criteria for matching data items. Only those data items matching the criteria specified in this structure are enumerated. See below.

 

Spare1, Spare2 — unused and must be 0.

 

Callback — supplies the address of a caller-supplied routine that the helper/callback calls once with each matching data item. See below.

 

Context — supplies a value meaningful to the caller, which is passed through unchanged and uninterpreted to the Callback routine.

 

Return Value:

 

The return value is a win32 error code. NO_ERROR indicates that all matching data items were successfully enumerated and passed to the Callback routine without errors. A return value other than NO_ERROR is returned if the Callback routine returns a value other than NO_ERROR. The return value in this case is the value the Callback routine returned.

 

 

The data items to be enumerated are specified in a structure that is passed to the helper/callback routine. Note that the criteria specified by the various members of this structure are ANDed together (i.e., the reporting plug-in matches, AND the data item type matches, AND the address range matches, AND the type specific data matches) subject to the flags set in the Flags member. The structure is as follows.

 

typedef struct _KA_ENUM_STORED_ITEM_SPECIFICATION {
            ULONG32 Flags;
            LPCWSTR ReportedPlugIn;
            LPCWSTR TypeSpecification;
            UINT_PTR StartAddress;
            UINT_PTR EndAddress;
            UINT_PTR TypeSpecificParam;
}
KA_ENUM_STORED_ITEM_SPECIFICATION, *PKA_ENUM_STORED_ITEM_SPECIFICATION;

 

Flags — supplies a set of bit flags that control operation of the enumeration.

 

KA_ESI_FLAG_USE_PLUGIN_HANDLE — indicates that ReportedPlugIn is not a plug-in string identifier, but a plug-in handle (HKAPLUGIN) instead.

KA_ESI_FLAG_USE_TYPE_HANDLE — indicates that TypeSpecification is not the name of a type specified as a string, but as a type handle (HKATYPE) instead.

KA_ESI_FLAG_ENUM_ALL_OVERLAPPED_ITEMS — indicates that all items that overlap with the range specified by StartAddress and EndAddress in any way are to be enumerated. If this flag is not set, only those items that are entirely contained within that range are enumerated.

KA_ESI_FLAG_SEARCH_TYPE_SPECIFIC_PARAM — indicates that the TypeSpecificParam must match the scalar type-specific parameter of a data item for the data item to be enumerated. If this flag is not set, TypeSpecificParam is ignored.

 

ReportedPlugIn — specifies the matching criteria for the plug-in that reported data items. Use this member to enumerate all items reported by a particular plug-in. This is either a plug-in string identifier, or a plug-in handle, depending on Flags. If not specified, data items are not filtered by reporting plug-in (i.e., all data items potentially match, depending on the other criteria in the structure).

 

TypeSpecification — specifies data item type criteria. Use this member to enumerate all data items of a particular type. This is either a type name, or a type handle, depending on Flags. If not specified, data items are not filtered by type (i.e., all data items potentially match, depending on the other criteria in the structure).

 

StartAddress — supplies the start of an address range that filters data items based on their location in kernel space. To eliminate this filtering (i.e., return all data items at any address, subject to the other criteria in the structure), set StartAddress to 0 and EndAddress to –1. Also see the description of Flags field above for the KA_ESI_FLAG_ENUM_ALL_OVERLAPPED_ITEMS flag.

 

EndAddress — see StartAddress.

 

TypeSpecificParam — if the KA_ESI_FLAG_SEARCH_TYPE_SPECIFIC_PARAM flag is set, then this member supplies the scalar type-specific value for data items to be enumerated. This member is ignored if that flag is not set.

 

 

Matching data items are passed to a caller-supplied callback routine. The callback routine is defined as follows.

 

typedef
UINT32
(CALLBACK *PKANALYZE_ENUM_STORED_ITEM_CALLBACK)(
            IN HKAPLUGIN PlugInHandle,
            IN KA_ITEM_ID DataItemId,
            IN OUT PVOID Context
            );

 

Parameters:

 

PlugInHandle — supplies the calling plug-in's handle, as returned by the registration callback routine at plug-in registration time.

 

DataItemId — supplies the identifier for the matching data item. Additional information about the data item can be retrieved by using the query data item helper/callback routine.

 

Context — this is the value passed as the Context parameter to the helper/callback routine. Kanalyze passes this value unchanged to the callback routine.

 

Return Value:

 

The return value is a win32 error code. Returning a value other than NO_ERROR causes enumeration to abort. The helper/callback routine immediately returns the returned value to the caller in this case. Returning NO_ERROR allows the enumeration to continue.

 

Table of Contents Ý

 

4.3.16                       Enumerating Data Item Links

A plug-in can enumerate data item links (i.e., data items to which a data item points and data items that point to a data item) using the enum link info helper/callback routine.

 

typedef
UINT32
(CALLBACK *KANALYZE_ENUM_LINK_INFO_ROUTINE)(
            IN HKAPLUGIN PlugInHandle,
            IN KA_ITEM_ID DataItemId,
            IN UINT_PTR Spare1,
            IN UINT_PTR Spare2,
            IN PKANALYZE_ENUM_LINK_INFO_CALLBACK Callback,
            IN OUT PVOID Context
            );

 

Parameters:

 

PlugInHandle — supplies the calling plug-in's handle, as returned by the registration callback routine at plug-in registration time.

 

DataItemId — supplies the identifier of the data item whose links are to be enumerated. Both those data items that point to this data item, and the data items to which this data item points, are enumerated. If not specified, links for all data items are enumerated.

 

Spare1, Spare2 — unused and must be 0.

 

Callback — supplies the address of a caller-supplied routine that the helper/callback calls once with each matching data item link. See below.

 

Context — supplies a value meaningful to the caller, which is passed through unchanged and uninterpreted to the Callback routine.

 

Return Value:

 

The return value is a win32 error code. NO_ERROR indicates that all matching data item links were successfully enumerated and passed to the Callback routine without errors. A return value other than NO_ERROR is returned if the Callback routine returns a value other than NO_ERROR. The return value in this case is the value the Callback routine returned.

 

 

Matching data item links are passed to a caller-supplied callback routine. The callback routine is defined as follows.

 

typedef
UINT32
(CALLBACK *PKANALYZE_ENUM_LINK_INFO_CALLBACK)(
            IN HKAPLUGIN PlugInHandle,
            IN CONST KA_LINK_INFO *LinkInfo,
            IN OUT PVOID Context
            );

 

Parameters:

 

PlugInHandle — supplies the calling plug-in's handle, as returned by the registration callback routine at plug-in registration time.

 

LinkInfo — supplies a pointer to a link information structure (see below). The callback routine must not write into this structure or any storage to which members of this structure point.

 

Context — this is the value passed as the Context parameter to the helper/callback routine. Kanalyze passes this value unchanged to the callback routine.

 

Return Value:

 

The return value is a win32 error code. Returning a value other than NO_ERROR causes enumeration to abort. The helper/callback routine immediately returns the returned value to the caller in this case. Returning NO_ERROR allows the enumeration to continue.

 

 

Link information is reported in a structure as follows.

 

typedef struct _KA_LINK_INFO {
            LPCWSTR ReportedPlugInName;
            KA_ITEM_ID SourceDataItemId;
            KA_ITEM_ID TargetDataItemId;
} KA_LINK_INFO, *PKA_LINK_INFO;

 

ReportedPlugInName — is the string identifier of the plug-in that reported the data item link.

 

SourceDataItemId — is the identifier of the source of the data item link (i.e., pointer).

 

TargetDataItemId — is the identifier of the target of the data item link (i.e., pointer target).

 

Table of Contents Ý

 

4.3.17                       Retrieving A Data Item’s Type-Specific Data

A plug-in can retrieve the non-scalar portion of a data item’s type-specific data using the retrieve type specific data helper/callback routine. Note that the scalar type-specific data is available in the data item information returned by the query data item helper/callback, and is not returned here.

 

typedef
UINT32
(CALLBACK *KANALYZE_RETRIEVE_TYPE_SPECIFIC_DATA_ROUTINE)(
            IN HKAPLUGIN PlugInHandle,
            IN KA_ITEM_ID DataItemId,
            IN SIZE_T TypeSpecificDataBufferSize,
            OUT PVOID TypeSpecificDataBuffer,
            OUT PSIZE_T TypeSpecificDataSize
            );

 

Parameters:

 

PlugInHandle — supplies the calling plug-in's handle, as returned by the registration callback routine at plug-in registration time.

 

DataItemId — supplies the identifier of the data item whose type-specific data is to be retrieved.

 

TypeSpecificDataBufferSize — supplies the size in bytes of the buffer pointed to by TypeSpecificDataBuffer.

 

TypeSpecificDataBuffer — supplies a pointer to storage into which the helper/callback routine will copy the type-specific data.

 

TypeSpecificDataSize — receives the actual size of the type-specific data. The actual size of the type-specific data is always returned in this value, even if the data is too large to fit in the caller-provided buffer.

 

Return Value:

 

The return value is a Win32 error code. If the return value is ERROR_MORE_DATA, then the buffer supplied by the caller was too small, and as much data as would fit was copied into TypeSpecificDataBuffer. The caller can check TypeSpecificDataSize for the size required to hold the entire data.

 

Table of Contents Ý

 

4.3.18                       Retrieving a Human-Readable Description of a Data Item

Every data item has an associated human-readable description. The plug-in that supports a data item is required to materialize this description in response to the get data item description helper/callback routine. The internal processing for this helper/callback causes KA_FORMAT_DATA_ITEM_DESCRIPTION to be sent to the plug-in that owns the data item whose description is being requested.

 

typedef
UINT32
(CALLBACK *KANALYZE_GET_DATA_ITEM_DESCRIPTION)(
            IN HKAPLUGIN PlugInHandle,
            IN KA_ITEM_ID DataItemId,
            IN SIZE_T MessageBufferSize,
            IN LPWSTR MessageBuffer,
            OUT PSIZE_T CaractersWritten  OPTIONAL
            );

 

Parameters:

 

PlugInHandle — supplies the calling plug-in's handle, as returned by the registration callback routine at plug-in registration time.

 

DataItemId — supplies the identifier of the data item whose human-readable description is desired.

 

MessageBufferSize — supplies the size in Unicode characters of the buffer pointed to by MessageBuffer.

 

MessageBuffer — supplies a pointer to storage into which the helper/callback routine will write the human-readable description of the data item whose identifier is given by DataItemId.

 

CharactersWritten — if specified, receives the number of Unicode characters the plug-in wrote into the buffer pointed to by MessageBuffer, or the number of characters required. In the success case, this does not include the terminating nul. In the non-success case, this includes the terminating nul. This is useful to allow the buffer to be resized.

 

Return Value:

 

The return value is a Win32 error code indicating the outcome of the operation. If the supplied buffer is too small, the return value is ERROR_MORE_DATA and the number of characters required (including the terminating nul) is copied to CharactersWritten. ERROR_INVALID_DATA indicates that there is no plug-in supporting the given data item (indicating that DataItemId is invalid).

 

Table of Contents Ý

 

4.3.19                       Calling a Method Interface Routine

A plug-in can call a method interface for a data item using the call method helper/callback routine. Method interfaces are type-specific routines for particular data items; the method interface routine is supplied when a type is registered (KA_REGISTER_TYPES) by a plug-in.

 

typedef
UINT32
(CALLBACK *KANALYZE_CALL_METHOD_ROUTINE)(
            IN HKAPLUGIN PlugInHandle,
            IN KA_ITEM_ID ItemId,
            IN ULONG32 MethodCode,
            ...
            );

 

Parameters:

 

PlugInHandle — supplies the calling plug-in's handle, as returned by the registration callback routine at plug-in registration time.

 

ItemId — supplies the identifier of the data item that is the “target” for the method interface invocation.

 

MethodCode — supplies a method code meaningful to the plug-in that supports the data item given by ItemId.

 

Additional arguments are MethodCode-specific.

 

Return Value:

 

The return value is a Win32 error code indicating the outcome of the operation. ERROR_MOD_NOT_FOUND indicates that no plug-in supports the given data item (i.e., ItemId is probably invalid) or that the supporting plug-in does not have a method interface routine. Other error codes are as returned by the supporting plug-in’s method interface routine.

 

Table of Contents Ý

 

4.3.20                       Locating a Published Helper/Callback Table

A plug-in can locate a public helper/callback table published by another plug-in using the get helper table helper/callback routine.

 

typedef
UINT32
(CALLBACK *KANALYZE_GET_HELPER_TABLE_ROUTINE)(
            IN HKAPLUGIN PlugInHandle,
            IN LPCWSTR PublicHelperTableName,
            OUT PVOID *PublicHelperTable,
            UINT_PTR Reserved
            );

 

Parameters:

 

PlugInHandle — supplies the calling plug-in's handle, as returned by the registration callback routine at plug-in registration time.

 

PublicHelperTableName — supplies the string identifier of the helper/callback routine table to be retrieved. Helper/callback routine table names are case-insensitive.

 

PublicHelperTable — receives a pointer to the helper/callback table. A helper/callback table consists of a SIZE_T value, which indicates the number of routines in the table, followed by pointers to each of these routines. The caller must not write into or free the storage pointed to by the value it receives here.

 

Reserved — unused and must be 0.

 

Return Value:

 

The return value is a Win32 error code indicating the outcome of the operation. ERROR_FILE_NOT_FOUND indicates that the given PublicHelperTableName is not published by any plug-in (i.e., does not exist).

 

Table of Contents Ý

 

4.3.21                       Broadcasting a Message to All Plug-Ins

A plug-in can cause a message to be broadcast to each plug-in’s interface routine using the broadcast message helper/callback routine. Note that the message is broadcast to the calling plug-in as well. The message being broadcast can be either a standard operation or a private operation (KA_PRIVATE).

 

typedef
UINT32
(CALLBACK *KANALYZE_BROADCAST_MESSAGE_ROUTINE)(
            IN HKAPLUGIN PlugInHandle,
            IN LPCWSTR ClassName,
            IN ULONG32 MessageCode,
            IN UINT_PTR Param1,
            IN PVOID Param2,
            UINT_PTR Reserved
            );

 

Parameters:

 

PlugInHandle — supplies the calling plug-in's handle, as returned by the registration callback routine at plug-in registration time.

 

ClassName — unused. Pass NULL for this parameter.

 

MessageCode — supplies the message to be sent to each plug-in. This can be in the standard range or the private range (KA_PRIVATE or above). If a standard message (< KA_PRIVATE) is broadcast, and a plug-in’s interface routine returns anything other than NO_ERROR, then that plug-in will be disabled and no longer participate in kanalyze.

 

Param1, Param2 — supply the MessageCode-specific parameters to be sent with the message.

 

Reserved — unused and must be 0.

 

Return Value:

 

The return value will be one of NO_ERROR or ERROR_CANCELLED, the latter indicating that the user elected to abort/cancel kanalyze.

 

Table of Contents Ý

 

5.      Engine Interface

The kanalyze engine is implemented as a DLL. The DLL exports several routines for the purposes of inclusion into an executable program. These routines are intended to be called by a kanalyze executable program, in a particular order and with certain constraints. This section describes these exported routines and how to make use of them.

 

KanalyzeDllInitialize — Initialize the kanalyze engine

KanalyzeSetParameter — Set a kanalyze parameter

KanalyzeGetParameter — Retrieve a kanalyze parameter

KanalyzeLoadDumpFile — Instruct the kanalyze engine to load a crash dump file

KanalyzeUnloadDumpFile — Instruct the kanalyze engine to unload the currently loaded dump file and symbols

KanalyzeLoadSymbols — Instruct the kanalyze engine to load symbols for the currently loaded dump file

KanalyzeUnloadSymbols — Instruct the kanalyze engine to unload the currently loaded symbols

KanalyzeLoadPlugIns — Instruct the kanalyze engine to load and initialize all plug-ins

KanalyzeConnectDatabase — Instruct the kanalyze engine to attempt to connect to a known issues database

KanalyzeDisconnectDatabase — Instruct the kanalyze engine to disconnect from a known issues database

KanalyzeLocateItemsAndAnalyze — Instruct the kanalyze engine to enter the analysis phase

KanalyzeSearchDatabase — Instruct the kanalyze engine to perform a database query against the known issues database to which it is connected

KanalyzeUpdateDatabase — Instruct the kanalyze engine to update the known issues database to which it is connected

KanalyzeProcessResults — Instruct the kanalyze engine to enter the results phase of analysis

KanalyzeTerminate — Shut down the kanalyze engine

 

The kanalyze engine is in kanalyze.dll. The export library is kanalyze.lib. The public header file is kanalyze.h.

 

Table of Contents Ý

 

5.1      Initializing the Kanalyze Engine

A kanalyze executable must call KanalyzeDllInitialize prior to calling any other routine exported by kanalyze.dll. Calling this routine causes the engine to initialize itself, and to start logging.

 

HKANALYZE
WINAPI
KanalyzeDllInitialize(
            IN LPCWSTR ParameterFileName OPTIONAL,
            IN PKA_INITIALIZE_PARAMS InitParams OPTIONAL
            );

 

Parameters:

 

ParameterFileName — optionally supplies a Win32 file specification for a kanalyze parameters file. If specified, an initial set of kanalyze parameters are read from this file. Most parameters can be overridden or added by using KanalyzeSetParameter. However the verbosity parameter and the logging-related parameters are used before KanalyzeDllInitialize returns and so no override of these is possible. If this parameter is not specified, a reasonable set of defaults is used by the engine; however certain plug-ins require information and thus if no parameters file is to be used, the kanalyze executable should be certain to call KanalyzeSetParameter as appropriate. Once KanalyzeDllInitialize returns, the actual on-disk copy of the parameters file is never referenced again.

 

InitParams — optionally specifies information used to “bind” the kanalyze executable to the kanalyze engine. This is described below.

 

Return Value:

 

The return value is an opaque value that must be supplied as the hKanalyze parameter when calling the other engine interface routines described in this section. NULL indicates that the engine was unable to initialize. The caller can call the GetLastError API to retrieve extended error information.

 

 

When a kanalyze executable initializes the kanalyze engine, it can supply some information to the engine via the InitParams parameter of KanalyzeDllInitialize. The engine uses this information at various points to call back into the executable for certain services.

 

typedef struct _KANALYZE_INITIALIZE_PARAMS {
            ULONG SizeOfStruct;
            PKANALYZE_REGISTER_PLUG_INS fnPlugInRegistration;
            PKANALYZE_OUTPUTSTREAM_HANDLER fnOutputStream;
            PKANALYZE_INPUTREQUEST_HANDLER fnInputRequest;
            PKANALYZE_CANCELINQUIRY_HANDLER fnCancelInquiry;
} KANALYZE_INITIALIZE_PARAMS, *PKANALYZE_INITIALIZE_PARAMS;

 

SizeOfStruct — must be set to sizeof(KANALYZE_INITIALIZE_PARAMS) prior to calling KanalyzeDllInitialize.

 

fnPlugInRegistration — for the sake of convenience, a kanalyze executable can contain plug-ins. If this is the case, this member supplies the address of a plug-in registration routine, analogous to the KanalyzeRegisterPlugIns routine exported from a plug-in DLL. The engine will call this routine immediately after all DLL-based plug-ins (and internal engine plug-ins) have registered (in other words, plug-ins embedded in a kanalyze executable are last in the plug-in ordering). If this member is not specified, then the kanalyze executable has no built-in plug-ins.

 

fnOutputStream — supplies a callback routine to which the engine passes all output, which includes errors and fatal errors written to the log via the write to log helper/callback; progress messages produced by the engine; and output passed to the string output helper/callback routine of the UiStream plug-in. If this member is not specified, then all such output is silently thrown away.

 

fnInputRequest — supplies a callback routine to which the engine forwards requests for input that are generated when plug-ins call the input request helper/callback routine of the UiStream plug-in. The kanalyze executable should display the prompt and allow the user to type in a string in response. If this member is not specified, then such requests for input are immediately failed with a return value of –1, indicating no input could be read.

 

fnCancelInquiry — supplies a callback routine which the engine calls periodically to determine if the user has canceled.

 

Table of Contents Ý

 

5.2      Setting and Retrieving Kanalyze Parameters

Various plug-ins and the kanalyze engine itself require parameterized operation. The KanalyzeSetParameter and KanalyzeGetParameter routines provide the interface to a centrally managed set of parameters corresponding to data in a kanalyze parameters file. A kanalyze parameters file is a standard Windows .ini file consisting of a set of bracketed section names, and lines within these sections having a left hand side, an equals sign, and a right hand side. Setting and retrieving kanalyze parameters via KanalyzeSetParameter and KanalyzeGetParameter logically follows this layout and is discussed in these terms below.

 

Kanalyze parameters can be overridden or set using KanalyzeSetParameter.

 

BOOL
WINAPI
KanalyzeSetParameter(
            IN HKANALYZE hKanalyze,
            IN ULONG Flags,
            IN LPCWSTR Parameter,
            IN LPCWSTR SubKey,
            IN PVOID Data
            );

 

Parameters:

 

hKanalyze — supplies the opaque value returned from KanalyzeDllInitialize.

 

Flags — supplies a set of flag values controlling certain aspects of the operation of this routine.

 

KAE_FLAG_DATA_INTEGER (0) — indicates that the data is scalar. Data is interpreted as a scalar value in this case.

KAE_FLAG_DATA_STRING — indicates that the data is a string. Data is interpreted as a pointer to a 0-terminated Unicode string in this case.

KAE_FLAG_FORCE_UPDATE — if specified and the data already exists, then it is overwritten. If the data already exists and this flag is not specified, then the routine fails with ERROR_FILE_EXISTS. May not be combined with KAE_FLAG_REMOVE_ENTRY.

KAE_FLAG_REMOVE_ENTRY — specifies that the data is to be removed. May not be combined with KAE_FLAG_FORCE_UPDATE.

 

Parameter — supplies the name of the parameter to be set. See the remarks section for a discussion of the usage of the Parameter and SubKey parameters.

 

SubKey — supplies the name of the subkey to be set. See the remarks section for a discussion of the usage of the Parameter and SubKey parameters.

 

Data — supplies the data for the parameter. This value is interpreted as either a string or a scalar value, depending on the supplied Flags.

 

Return Value:

 

The return value is a Boolean indicating whether the operation succeeded or failed. If 0 is returned, the caller can call the GetLastError API to retrieve extended error information.

 

Remarks:

 

In general, the SubKey parameter supplies the name of a section within a kanalyze parameter (.ini) file and the Parameter parameter supplies the name (i.e., left hand side) of a line within the section.

 

            [MyPlugIn]              ß SubKey = MyPlugIn

            foo = some_value        ß Parameter = foo

 

There is one exception. If SubKey is NULL, then Parameter is a so-called “global” parameter, which corresponds to a line in the [kanalyze] section of the kanalyze parameters .ini file.

 

     [kanalyze]              ß SubKey = NULL

     bar = some_other_value  ß Parameter = bar

 

 

Kanalyze parameters can be retrieved using KanalyzeGetParameter.

 

BOOL
WINAPI
KanalyzeGetParameter(
            IN HKANALYZE hKanalyze,
            IN ULONG Flags,
            IN LPCWSTR Parameter,
            IN LPCWSTR SubKey,
            OUT PVOID Data,
            PVOID Reserved
            );

 

Parameters:

 

hKanalyze — supplies the opaque value returned from KanalyzeDllInitialize.

 

Flags — supplies a set of flag values controlling certain aspects of the operation of this routine.

 

KAE_FLAG_DATA_INTEGER (0) — indicates that the data is scalar. In this case Data is interpreted as a pointer to a 32-bit integer, which receives the value on output. If the requested data is not actually an integer, the routine fails with ERROR_FILE_NOT_FOUND.

KAE_FLAG_DATA_STRING — indicates that the data is a string. Data is interpreted as a pointer to an LPCWSTR, which receives a pointer to the engine’s internal copy of the string. The caller must not attempt to free or modify the storage occupied by this string.

KAE_FLAG_GET_PARAMETER_BY_ORDER — indicates that the nth (0-based) value in a set of related values (corresponding to the nth line in a section in the kanalyze parameters .ini file) is to be retrieved. See the remarks section for further discussion.

 

Parameter — supplies the name of the parameter to be set. See the remarks section for a discussion of the usage of the Parameter and SubKey parameters.

 

SubKey — supplies the name of the subkey to be set. See the remarks section for a discussion of the usage of the Parameter and SubKey parameters.

 

Data — receives the data for the parameter. This value is interpreted as a pointer to storage into which the engine places a 32-bit integer or a pointer to a string, depending on the supplied Flags and Parameter values. See the remarks section for further discussion.

 

Return Value:

 

The return value is a Boolean indicating whether the operation succeeded or failed. If 0 is returned, the caller can call the GetLastError API to retrieve extended error information.

 

Remarks:

 

The basic functioning of the Parameter and SubKey values is the same as was described above for KanalyzeSetParameter.

 

KanalyzeGetParameter can be used to enumerate a set of related values, corresponding to the lines in a section of the kanalyze parameters .ini file. The caller first calls with Parameter set to KAE_PARAM_GET_NUMBER_OF_ENTRIES and SubKey set to the name of the section to be enumerated. This places a 32-bit count into the storage pointed to by Data. Then the caller can retrieve the right hand side of the nth line in the section by passing in the KAE_FLAG_GET_PARAMETER_BY_ORDER flag, with Parameter set to the 0-based index of the line whose right hand side is to be retrieved, and SubKey set to the name of the section.

 

A kanalyze executable sets and retrieves parameters at various points in its operation. These routines can be called at any time after KanalyzeDllInitialize has been successfully called. Other sections below document the parameters that are used during kanalyze operation and when they are used. The kanalyze executable must ensure that any required parameters have been set up prior to calling a particular engine interface routine or the results are undefined, and include the possibility of fatal application exceptions.

 

Table of Contents Ý

 

5.3      Loading and Unloading Crash Dump Files

A kanalyze executable must either cause a crash dump file to be loaded, or indicate to the engine that a crash dump file will not be used (i.e., a pre-existing signature id file will be used instead of a dump file) by using KanalyzeLoadDumpFile. If a crash dump file is to be used then the dumpfile “global” parameter (i.e., “dumpfile =” line in the [kanalyze] section of the parameters file) must be set to the win32 file spec of the crash dump file. An empty/nonexistent dumpfile parameter indicates that no dump file is to be used (a pre-existing signature id file will be used instead), but note that the engine does not deal with the signature id file until later, when plug-ins are loaded.

 

Only one dump file can be loaded at a time. If the executable determines that a different dump file should be loaded, then it must call KanalyzeUnloadDumpFile before attempting the load. Note that this makes sense and is possible only before the executable has caused plug-ins to be loaded (KanalyzeLoadPlugIns). Also note that calling KanalyzeUnloadDumpFile when a dump file is not actually loaded is a safe operation, and that unloading a dump file automatically unloads any symbols currently loaded (i.e., an implicit call to KanalyzeUnloadSymbols is made internally).

 

The kanalyze executable should call KanalyzeLoadDumpFile some time after calling KanalyzeDllInitialize but before causing symbols to be loaded (KanalyzeLoadSymbols).

 

The engine passes messages generated during dump file load to a registered output handler if one was provided when the kanalyze executable initialized the kanalyze engine (KanalyzeDllInitialize).

 

The kanalyze executable causes a dump file to be loaded (or indicates that there is no dump file) with KanalyzeLoadDumpFile.

 

BOOL
WINAPI
KanalyzeLoadDumpFile(
            IN HKANALYZE hKanalyze,
            OUT LPWSTR FailureDescription,
            IN DWORD BufferLength
            );

 

Parameters:

 

hKanalyze — supplies the opaque value returned from KanalyzeDllInitialize.

 

FailureDescription — if the routine returns 0 indicating an error, the buffer pointed to by this parameter receives a human-readable description of the failure. The executable should present this string to the user and invoke any retry logic, possibly calling KanalyzeLoadDumpFile again.

 

BufferLength — supplies the size in Unicode characters of the buffer pointed to by FailureDescription.

 

Return Value:

 

The return value is a Boolean indicating whether the operation succeeded or failed. If 0 is returned, the caller should present the string returned in FailureDescription to the user and invoke retry logic. GetLastError can also be used to retrieve extended error information.
ERROR_INVALID_PARAMETER — hKanalyze is invalid
ERROR_ALREADY_EXISTS — a dump file is already loaded
ERROR_BAD_FORMAT — the underlying crashlib failed to load the dump file
ERROR_NOT_SUPPORTED — the crash dump is for an unsupported platform

 

The kanalyze executable can cause the currently loaded dump file to be unloaded with KanalyzeUnloadDumpFile. Calling this routine when no dump file is actually loaded is a safe operation.

 

BOOL
WINAPI
KanalyzeUnloadDumpFile(
            IN HKANALYZE hKanalyze
            );

 

Parameters:

 

hKanalyze — supplies the opaque value returned from KanalyzeDllInitialize.

 

Return Value:

 

The return value is a Boolean indicating whether the operation succeeded or failed. Currently, this is always TRUE unless hKanalyze is invalid.

 

Table of Contents Ý

 

5.4      Loading and Unloading Symbols

In the case where a dump file is to be used (i.e., a pre-existing signature id file is not being used), the kanalyze executable must cause symbols to be loaded after loading the dump file but before moving on to any other activity. KanalyzeLoadSymbols is used for this. Prior to calling KanalyzeLoadSymbols, the executable must ensure that the symbols parameters are set up correctly (corresponding to the [symbols] section of the kanalyze parameters file).

 

Only one set of symbols can be loaded at a time, and symbol loading will fail entirely if at least the symbols for ntoskrnl.exe cannot be loaded. If the kanalyze executable wants to retry symbol loading, it must first call KanalyzeUnloadSymbols. Note that this makes sense and is possible only before the executable has caused plug-ins to be loaded (KanalyzeLoadPlugIns). Also note that calling KanalyzeUnloadSymbols when symbols are not actually loaded is a safe operation, and that unloading a dump file (KanalyzeUnloadDumpFile) automatically unloads any symbols currently loaded (i.e., an implicit call to KanalyzeUnloadSymbols is made internally).

 

The engine passes messages generated during symbol load to a registered output handler if one was provided when the kanalyze executable initialized the kanalyze engine (KanalyzeDllInitialize).

 

The kanalyze executable causes symbols to be loaded with KanalyzeLoadSymbols.

 

BOOL
WINAPI
KanalyzeLoadSymbols(
            IN HKANALYZE hKanalyze,
            OUT LPWSTR FailureDescription,
            IN DWORD BufferLength
            );

 

Parameters:

 

hKanalyze — supplies the opaque value returned from KanalyzeDllInitialize.

 

FailureDescription — if the routine returns 0 indicating an error, the buffer pointed to by this parameter receives a human-readable description of the failure. The executable should present this string to the user and invoke any retry logic, possibly calling KanalyzeLoadSymbols again.

 

BufferLength — supplies the size in Unicode characters of the buffer pointed to by FailureDescription.

 

Return Value:

 

The return value is a Boolean indicating whether the operation succeeded or failed. If 0 is returned, the caller should present the string returned in FailureDescription to the user and invoke retry logic. GetLastError can also be used to retrieve extended error information.
ERROR_INVALID_PARAMETER — hKanalyze is invalid
ERROR_ALREADY_EXISTS — symbols are already loaded
ERROR_INVALID_DATA — symbols for the kernel could not be loaded
ERROR_CANCELLED — kanalyze operation was cancelled (such as by the user)

 

The kanalyze executable can cause the currently loaded symbols to be unloaded with KanalyzeUnloadSymbols. Calling this routine when no symbols are actually loaded is a safe operation.

 

BOOL
WINAPI
KanalyzeUnloadSymbols(
            IN HKANALYZE hKanalyze
            );

 

Parameters:

 

hKanalyze — supplies the opaque value returned from KanalyzeDllInitialize.

 

Return Value:

 

The return value is a Boolean indicating whether the operation succeeded or failed. Currently, this is always TRUE unless hKanalyze is invalid.

 

Table of Contents Ý

 

5.5      Loading Plug-Ins

After a dump file and symbols have been loaded (or the kanalyze executable has indicated that it will not use a dump file) with KanalyzeLoadDumpFile and KanalyzeLoadSymbols, the kanalyze executable must cause plug-ins to be loaded with KanalyzeLoadPlugIns. This must be done before any analysis or database activity can take place.

 

The engine loads, registers, and initializes the plug-ins in the following sequence. The actions listed below are performed synchronously with the call to KanalyzeLoadPlugIns.

 

·          DLLs listed in the [plugins] section of the kanalyze parameters .ini file (or set via KanalyzeSetParameter) are physically loaded in the order listed/set, and the registration entry point address is retrieved and saved away;

·          The registration entry point of each DLL loaded in the previous step is called, in the order the DLLs were loaded;

·          Internal engine plug-ins are registered;

·          The kanalyze executable is given a chance to register any plug-ins it itself contains, via the callback routine the executable passed to the engine when it called KanalyzeDllInitialize;

·          Pass 0 KA_INITIALIZE is sent to each plug-in, in the order the plug-ins were registered;

·          Pass 1 KA_INITIALIZE is sent to each plug-in, in the order the plug-ins were registered;

·          KA_REGISTER_TYPES is sent to each plug-in, in the order the plug-ins were registered.

 

Following successful completion of these steps, the engine opens or creates the signature id file. The signature id file is created (and overwritten if it exists) if a dump file is being used. The signature id file is opened if a dump file is not being used (i.e., a pre-existing sigidfile is being used instead of a dump file). Thus prior to calling KanalyzeLoadPlugIns, the kanalyze executable must ensure that the signature id file “global” parameter is set (i.e., corresponding to the “signature id file =” line in the [kanalyze] section of the parameters file). If this parameter is not set, a default value of .\sigidfil.sgd is used.

 

During processing of KanalyzeLoadPlugIns, the engine also examines the DisableExceptionHandler “global” parameter (i.e., corresponding to the “disableexceptionhandler =” line in the [kanalyze] section of the parameters file). If this parameter is set to anything other than 1, all calls to the interface routine of any plug-in are enclosed in try/except. If this parameter is 1, then such calls are unguarded. Turning off this internal exception handling can be useful for debugging purposes.

 

BOOL
WINAPI
KanalyzeLoadPlugIns(
            IN HKANALYZE hKanalyze
            );

 

Parameters:

 

hKanalyze — supplies the opaque value returned from KanalyzeDllInitialize.

 

Return Value:

 

The return value is a Boolean indicating whether the operation succeeded or failed. If 0 is returned, the caller can call GetLastError to retrieve extended error information.

 

 

Note that once this routine has been called successfully, the kanalyze executable must not call KanalyzeUnloadDumpFile or KanalyzeUnloadSymbols. There is no corresponding “unload” routine for KanalyzeLoadPlugIns.

 

Table of Contents Ý

 

5.6      Known Issues Database Functionality

With regard to the known issues database, the kanalyze executable must first cause a connection to a database to be established. Following that, queries can be instigated, and later the kanalyze executable can request that the database be updated based on the results of the queries, user input, and/or automated criteria. Finally, the kanalyze executable causes the database connection to be dropped. Thus the engine interfaces for known issues database functionality fall into 3 categories:

 

·          Connecting and disconnecting: KanalyzeConnectDatabase, KanalyzeDisconnectDatabase

·          Searching: KanalyzeSearchDatabase

·          Updating: KanalyzeUpdateDatabase

 

The sections that follow describe these in more detail.

 

Table of Contents Ý

 

5.6.1    Connecting and Disconnecting

After plug-ins have been successfully loaded (KanalyzeLoadPlugIns), the kanalyze executable can cause a connection to a known issues database to be established with KanalyzeConnectDatabase. The connection attempt occurs synchronously with the call to KanalyzeConnectDatabase and is based on the “query” parameters (i.e., corresponding to the [query] section of the kanalyze parameters file), which the caller must therefore ensure are set properly prior to calling KanalyzeConnectDatabase. If the connection attempt fails, the caller can invoke retry logic, possibly calling KanalyzeConnectDatabase again. Once KanalyzeConnectDatabase succeeds, the kanalyze executable should not call KanalyzeDisconnectDatabase until all database operations (KanalyzeSearchDatabase, KanalyzeUpdateDatabase) are complete. In other words, KanalyzeConnectDatabase and KanalyzeDisconnectDatabase are intended to bracket all other database operations.

 

Only one database connection can be established and once it has been established, the kanalyze executable must not attempt to establish another one, even after calling KanalyzeDisconnectDatabase.

 

Calling KanalyzeConnectDatabase causes the engine to send KA_DB_CONNECT with the DBF_CONNECT operation code serially to each plug-in until one of them indicates that it has established a connection or that it tried and failed.

 

BOOL
WINAPI
KanalyzeConnectDatabase(
            IN HKANALYZE hKanalyze,
            OUT PBOOL Connected
            );

 

Parameters:

 

hKanalyze — supplies the opaque value returned from KanalyzeDllInitialize.

 

Connected — if the routine returns success, receives a value indicating whether a connection has actually been established.

 

Return Value:

 

The return value is a Boolean indicating whether the operation succeeded or failed. Success for this routine means that either a plug-in successfully established a connection, or that no plug-in that handles connections is loaded and therefore no connection was attempted. In the success case, therefore, the caller must check the value stored in the storage pointed to by Connected. Failure means that a plug-in attempted a connection but failed. In this case the caller can call GetLastError to retrieve extended error information.

 

 

Calling KanalyzeDisconnectDatabase causes the engine to send the KA_DB_CONNECT with the DBF_DISCONNECT operation code serially to each plug-in until one of them indicates that it has handled the disconnect request.

 

BOOL
WINAPI
KanalyzeDisconnectDatabase(
            IN HKANALYZE hKanalyze
            );

 

Parameters:

 

hKanalyze — supplies the opaque value returned from KanalyzeDllInitialize.

 

Return Value:

 

The return value is a Boolean indicating whether the operation succeeded or failed. In the failure case the caller can call GetLastError to retrieve extended error information. If GetLastError returns –1, then no plug-in handled the disconnect request (this is an aberration that should not occur if the database plug-in is functioning properly).

 

Table of Contents Ý

 

5.6.2    Querying/Searching

Once a database connection has been established (KanalyzeConnectDatabase), the kanalyze executable can cause a database query to be executed at 2 separate points and with 2 different goals, by using KanalyzeSearchDatabase. A kanalyze executable can make use of either or both types of query.

 

·          Initial query or pre-query: An initial query determines whether the exact crash being analyzed exists in the database. The query is based on crash instance data taken automatically from the signature id file by the database plug-in; no other plug-ins participate. Therefore such a query can be executed at any time after the signature id file is created/opened after a successful call to KanalyzeLoadPlugIns.

·          Full query: A full query requires the participation of other plug-ins, which aid in the construction of the query itself based on the results of their analysis, in the form of canonicalized crash data. Therefore such a query can be performed only after the kanalyze executable has called KanalyzeLocateItemsAndAnalyze to order a detailed analysis. A full query is generally performed only if an initial query does not return any matching crash classes.

 

Calling KanalyzeSearchDatabase with the control code DBC_DO_PREQUERY causes the engine to send KA_DB_CONTROL with DBC_DO_PREQUERY until one plug-in indicates that it has handled the request and either actually performed the query or encountered an error. Calling with DBC_DO_FULLQUERY similarly causes the engine to send KA_DB_CONTROL with DBC_DO_FULLQUERY. For the full query case, see the discussion about the master database plug-in.

 

Following an initial query, the kanalyze executable can use the enum stored data item helper/callback routine to examine the \Analysis\DbPreMatching branch of the data item namespace to determine if any matches were found. Following a full query, \Analysis\DbMatching can be checked.

 

BOOL
WINAPI
KanalyzeSearchDatabase(
            IN HKANALYZE hKanalyze,
            IN UINT_PTR Control
            );

 

Parameters:

 

hKanalyze — supplies the opaque value returned from KanalyzeDllInitialize.

 

Control — supplies the KA_DB_CONTROL operation parameter. One of DBC_DO_PREQUERY or DBC_DO_FULLQUERY.

 

Return Value:

 

The return value is a Boolean indicating whether the operation succeeded or failed. In the failure case the caller can call GetLastError to retrieve extended error information. If GetLastError returns –1, then no plug-in handled the query request (this is an aberration that should not occur if KanalyzeConnectDatabase was successfully called earlier, and the master database plug-in is functioning properly).

 

Table of Contents Ý

 

5.6.3    Updating

By using KanalyzeUpdateDatabase, the kanalyze executable can cause the known issues database to be updated. This can be done at any time after a connection has been made to a database (KanalyzeConnectDatabase), though generally this occurs after a query has been performed (KanalyzeSearchDatabase). Based on user input or automated criteria, the executable can request the creation of a new crash class (allowed only if canonicalized data exists after a detailed analysis has actually been run), or a new instance within an existing class.

 

Calling KanalyzeUpdateDatabase results in the engine sending KA_DB_UPDATE until one plug-in indicates that it has (either successfully or unsuccessfully) processed the update request. To the caller of KanalyzeUpdateDatabase, the update occurs synchronously with the call.

 

BOOL
WINAPI
KanalyzeUpdateDatabase(
            IN HKANALYZE hKanalyze,
            IN PKA_DATABASE_UPDATE_PARAMS DbUpdateParams
            );

 

Parameters:

 

hKanalyze — supplies the opaque value returned from KanalyzeDllInitialize.

 

DbUpdateParams  — supplies parameters indicating how the database is to be updated. This structure is passed along by the engine when it calls plug-ins with KA_DB_UPDATE.

 

Return Value:

 

The return value is a Boolean indicating whether the operation succeeded or failed. In the failure case the caller can call GetLastError to retrieve extended error information. If GetLastError returns –1, then no plug-in handled the update request (this is an aberration that should not occur if KanalyzeConnectDatabase was successfully called earlier, and the master database plug-in is functioning properly).

 

Table of Contents Ý

 

5.7      Detailed Analysis

A kanalyze executable can optionally direct the engine to begin a detailed analysis phase by calling KanalyzeLocateItemsAndAnalyze. The detailed analysis phase consists of requesting plug-ins to locate and analyze their data items; the engine sends KA_START_LOCATE_ITEMS and KA_PERFORM_ANALYSIS to each plug-in. The item location and analysis proceeds synchronously with the call to KanalyzeLocateItemsAndAnalyze, and the kanalyze executable may receive progress messages for output, via the callback routine it passed to the engine when it called KanalyzeDllInitialize.

 

There is no requirement that the kanalyze executable call KanalyzeLocateItemsAndAnalyze; the detailed analysis phase can be skipped. An example of when this might be desirable would be when an initial database query (KanalyzeSearchDatabase) returns a match and the user therefore elects to skip analysis.

 

KanalyzeLocateItemsAndAnalyze must be called after plug-ins have been loaded (KanalyzeLoadPlugIns); it is typically called after an initial database query has been made with no matches and the user desires to continue on to perform a full query. When this routine returns, the signature id file has been fully populated with any canonical data, data blobs, and attachments.

 

BOOL
WINAPI
KanalyzeLocateItemsAndAnalyze(
            IN HKANALYZE hKanalyze
            );

 

Parameters:

 

hKanalyze — supplies the opaque value returned from KanalyzeDllInitialize.

 

Return Value:

 

The return value is a Boolean indicating whether the operation succeeded or failed. In the failure case the caller can call GetLastError to retrieve extended error information.

 

Table of Contents Ý

 

5.8      Processing Results

A kanalyze executable can direct the engine to send KA_PROCESS_RESULT to each plug-in by calling KanalyzeProcessResults. There is no requirement that the executable do this. KA_PROCESS_RESULT is typically processed only by director plug-ins. If the kanalyze executable calls KanalyzeProcessResults, it must do so at some point after calling KanalyzeLocateItemsAndAnalyze.

 

BOOL
WINAPI
KanalyzeProcessResults(
            IN HKANALYZE hKanalyze
            );

 

Parameters:

 

hKanalyze — supplies the opaque value returned from KanalyzeDllInitialize.

 

Return Value:

 

The return value is a Boolean indicating whether the operation succeeded or failed. In the failure case the caller can call GetLastError to retrieve extended error information.

 

Table of Contents Ý

 

5.9      Shutting Down the Kanalyze Engine

Once all kanalyze operations are finished, the kanalyze executable should shut down the kanalyze engine with KanalyzeTerminate. Calling this routine causes the signature id file to be closed, and the engine sends out KA_TERMINATE to each plug-in. Following this, no other engine routines can be called.

 

BOOL
WINAPI
KanalyzeTerminate(
            IN HKANALYZE hKanalyze
            );

 

Parameters:

 

hKanalyze — supplies the opaque value returned from KanalyzeDllInitialize.

 

Return Value:

 

The return value is a Boolean indicating whether the operation succeeded or failed. Currently, this is always TRUE unless hKanalyze is invalid.

 

Table of Contents Ý

 

6.      Database Matching and Processing

When kanalyze is running with a personality that includes signature id file generating or database matching and updating, a signature id file is built up during identification and analysis, and is populated by the end of the KA_PERFORM_ANALYSIS phase. Following this, a database query is built by calling each plug-in’s KA_DB_BUILD_QUERY routine.  The query is executed, and the returned (matching) classes are passed though an automated match processor. The match processor uses any hint data associated with the crash class to locate the best matches. After this, the returned classes are passed down to each plug-in via the KA_DB_PROCESS_CLASS interface routine. Plug-ins can examine the class, retrieve any additional data they may require from the database, etc.

 

The results of database matching are placed by plug-ins into the \Analysis\DbPreMatching and \Analysis\DbMatching branches of the data item namespace.

 

The following sections describe the process in more detail.

 

Table of Contents Ý

 

6.1      Signature Id File

At the end of the KA_PERFORM_ANALYSIS phase, the signature id file has been populated. The classes of information in the file include

 

1)      Canonical fixed crash data. This data is inserted by database-related analysis plug-ins.

2)      Instance crash data. This data is inserted by the kanalyze engine.

3)      Administrative data. This data is generally “stubbed” but can be inserted by director plug-ins, for example by prompting the user with a form.

4)      Fixed kanalyze fields. This data is inserted by the kanalyze engine.

5)      Attachments. This data is inserted by plug-ins (potentially including director plug-ins).

6)      Variable data. This data is inserted by plug-ins.

 

Table of Contents Ý

 

6.2      Building the Database Query

Each plug-in receives the KA_DB_BUILD_QUERY notification. The engine inserts ORs between each query string returned from a plug-in in response to this notification, to form a query that is the union of all classes being requested from the database by plug-ins.

 

The query is then executed by calling the database special plug-in.

 

KA_DB_BUILD_QUERY is passed to each plug-in exactly one time. Querying the database for matching crash class data is not an iterative process. The returned record set is guaranteed to contain the matching crash class if a match exists.

 

Table of Contents Ý

 

6.3      Processing Query Results (Matching Crash Classes)

After the query is executed, each matching class is examined in turn to determine whether it matches the crash under examination (as represented by the signature id file), by each plug-in. For some crashes in the known issues database, hint data may exist. Hint data is the embodiment of a person’s anslysis, and directs kanalyze to perform matchings on highly specific criteria. The presence of such data allows kanalyze to determine matches without the involvement of other analysis plug-ins.

 

For example, consider a crash where a broken driver foo.sys calls a system routine at elevated IRQL but where the symptom of this problem is a bugcheck in ntfs.sys. With a problem such as this, automatically determining the actual broken module is extremely difficult if not impossible since there is scant trace of the broken driver’s code path by the time the system actually crashes. Thus the (canonicalized) crash class data will indicate a relevant module of ntfs.sys (not foo.sys), and the query built up by the analysis plug-ins makes no mention of foo.sys. In other words, the database query is based entirely on the canonical evidence at hand.

 

If this crash has been seen previously, the returned crash class record set will include classes with ntfs.sys mentioned in the relevant (canonical) class data. A support engineer may have previously debugged the crash or received information from development, and determined that module foo.sys version 6.5 is actually at fault. The engineer then added hint data to the crash class in the database. In this case, an automated matching procedure in kanalyze need not involve any other analysis plug-ins to locate the “best” matches – the hint data directs it to see if foo.sys version 6.5 is present in the OS module list for the crash being examined. If it is, then there’s a strong match between the current crash and the crash in the database.

 

The automated crash matching procedure is simply a special case of the general matched class processing flow. Kanalyze calls each plug-in with KA_DB_PROCESS_CLASS for each class returned by the query to give it a chance to determine if and to what extent a class matches the current crash. If necessary, the plug-in can retrieve additional data related to the crash class or its associated instances from the known issues database, via the database plug-in.

 

The “output” of plug-ins during the KA_DB_PROCESS_CLASS phase is data items in the \Analysis\DbPreMatching and \Analysis\DbMatching branches of the data item namespace. These data items describe the matching, and can later be enumerated by a director plug-in and displayed to the user.

 

Table of Contents Ý