Previous Next

DbgPrintEx

DbgPrintEx sends a string to the kernel debugger if certain conditions are met.

ULONG
  DbgPrintEx(
    IN ULONG  ComponentId,
    IN ULONG  Level,
    IN PCHAR  Format,
    . . . .  [arguments] 
    );

Parameters

ComponentId
Specifies the component calling this routine. This must be one of the component name filter IDs defined in the DDK header ntddk.h and the SDK header ntrtl.h. To avoid mixing your driver's output with the output of Windows components, you should use only the following values for ComponentId:

DPFLTR_IHVDRIVER_ID

DPFLTR_IHVVIDEO_ID

DPFLTR_IHVAUDIO_ID

DPFLTR_IHVNETWORK_ID

DPFLTR_IHVSTREAMING_ID

DPFLTR_IHVBUS_ID

Level
Specifies the severity of the message being sent. This can be any 32-bit integer. Values between 0 and 31 (inclusive) are treated differently than values between 32 and 0xFFFFFFFF. For details, see the Comments section following.
Format
Specifies a pointer to the format string to print, as in printf. The Format string supports the printf-style formatting codes. However, the Unicode format codes (%C, %S, %lc, %ls, %wc, %ws, %wZ) can only be used at IRQL PASSIVE_LEVEL.
arguments
Specifies arguments for the format string, as in printf.

Return Value

If successful, DbgPrintEx returns the NTSTATUS code STATUS_SUCCESS; otherwise, it returns the appropriate error code.

Headers

This routine is defined in ntddk.h and ndis.h; component filter IDs are defined in ntddk.h. Include ntddk.h.

Comments

This routine can only be used in Windows XP and later.

Only kernel-mode drivers can call the DbgPrintEx routine.

Unless it is absolutely necessary, you should not obtain a string from user input or another process and pass it to DbgPrintEx. If you do use a string that you did not create, you must verify that this is a valid format string, and that the format codes match the argument list in type and quantity. The best coding practice is for all Format strings to be static and defined at compile time.

DbgPrintEx will either pass the specified string to the kernel debugger or do nothing at all, depending on the values of ComponentId, Level, and the corresponding component filter masks.

Each component has a separate filter mask. The components that are of interest to driver writers are IHVDRIVER, IHVVIDEO, IHVAUDIO, IHVNETWORK, IHVSTREAMING, and IHVBUS.

There are two ways to set a component filter mask:

Filter masks stored in the registry take effect during boot. Filter masks created by the debugger take effect immediately, and last until Windows is rebooted. A value set in the registry can be overridden by the debugger, but the component filter mask will return to the value specified in the registry if the system is rebooted.

Here is an example of how component filter masks can be set. Suppose that before the last boot, you created two values in the Debug Print Filter key: IHVVIDEO, with a value equal to DWORD 0x2, and IHVBUS, equal to DWORD 0x7FF. Now you issue the following commands in the kernel debugger:

kd> ed Kd_IHVVIDEO_Mask 0x8 
kd> ed Kd_IHVAUDIO_Mask 0x7 

At this point, the IHVVIDEO component has a filter mask of 0x8, the IHVAUDIO component has a filter mask of 0x7, and the IHVBUS component has a filter mask of 0x7FF.

There is also a system-wide mask called WIN2000. This is equal to one by default, though it can be changed through the registry or the debugger like all other components. When filtering is performed, each component filter mask is first ORed with the WIN2000 mask. So in this example, the IHVVIDEO mask is effectively equal to 0x9, and components whose filter masks have not been set at all (for instance, IHVSTREAMING) will have a filter mask of one.

When DbgPrintEx is called in kernel-mode code, Windows compares the message importance specified by Level with the filter mask of the component specified by ComponentId. This comparison is performed as follows:

The following constants can be useful for setting the value of Level. They are defined in the DDK header ntddk.h and the SDK header ntrtl.h:

#define   DPFLTR_ERROR_LEVEL     0
#define   DPFLTR_WARNING_LEVEL   1
#define   DPFLTR_TRACE_LEVEL     2
#define   DPFLTR_INFO_LEVEL      3
#define   DPFLTR_MASK    0x8000000

To make your driver compatible with the way Windows uses message levels, you should only set Level equal to DPFLTR_ERROR_LEVEL when a serious error occurs. (Since the WIN2000 system-wide filter is usually equal to one, these messages will be seen by anyone performing kernel debugging.) The warning, trace, and information levels should be used in the appropriate situations. Other bits can be freely used for any purposes that you find useful This allows you to have a wide variety of message types that can be selectively seen or hidden.

Continuing the example from the beginning of this section, suppose that the following function calls occur in your driver:

DbgPrintEx( DPFLTR_IHVVIDEO_ID,  DPFLTR_INFO_LEVEL,   "First message.\n");
DbgPrintEx( DPFLTR_IHVAUDIO_ID,  7,                   "Second message.\n");
DbgPrintEx( DPFLTR_IHVBUS_ID,    DPFLTR_MASK & 0x10,  "Third message.\n");

The first message will be transmitted, because DPFLTR_INFO_LEVEL is equal to 3; it is therefore treated as a bit shift, resulting in 0x8. This value is then ANDed with the effective IHVVIDEO component filter mask of 0x9, giving a nonzero result.

The second message will not be transmitted, because the Level value of 7 is treated as a bit shift, resulting in 0x80. This is then ANDed with the IHVAUDIO component filter mask of 0x7, giving a result of zero.

The third message will be transmitted, because DPFLTR_MASK & 0x10 is greater than 31, and is therefore treated as the literal DWORD 0x80000010. This is then ANDed with the IHVBUS component filter mask of 0x7FF, giving a nonzero result.

When the filter allows a message to be transmitted, the formatted string is sent to the DbgPrint Buffer. The contents of this buffer are displayed immediately in the Debugger Command window, unless this display has been disabled by using the Global Flags Editor (gflags.exe).

If this display has been disabled, the contents of the DbgPrint Buffer can only be viewed by using the !dbgprint extension command. For information on debugger extensions, see Debugging Tools for NT-Based Operating Systems.

There is no upper limit to the size of the Format string or the number of arguments. However, the DbgPrint buffer can only hold 512 bytes of information. Any output longer than this will be lost.

See Also

DbgPrint, KdPrint, KdPrintEx