If you’ve been using WinDbg for any amount of time, you’ve surely come across the Debugger Markup Language (DML). DML is what provides the ability to create hyperlinks in the debugger’s output window. For example, this support is used beautifully within the NDIS debugging extensions. Try running !ndiskd.help and clicking around a bit, even if you’re not familiar with NDIS debugging you have to be impressed by the ease of use DML creates.
Now, here’s something about DML that you might not know: you can print DML right from your driver code! All you need to do is place the special marker <?dml?> in your DbgPrint statement to indicate that the subsequent string is DML. Then craft the remainder of your string to be a DML statement and the debugger will do the rest.
For those not familiar with crafting their own DML statements, here’s a quick primer on what you can do.
Execute a WinDbg Command
The DML syntax for specifying a command link is as follows:
<exec cmd=”Command String”>Link Text</exec>
Thus, we can do something like this to automate looking up NTSTATUS values returned from failing functions:
status = PsSetLoadImageNotifyRoutine(ImageLoadNotify); if (!NT_SUCCESS(status)) { DbgPrint("API Failed! <?dml?> <exec cmd=\"!error 0x%x\">0x%x</exec>\n", status, status); }
This results in a DML link appearing in the output, which can then be clicked to get information about the error:
2: kd> p API Failed!? 0xc000009a 2: kd> !error 0xc000009a Error code: (NTSTATUS) 0xc000009a (3221225626) - Insufficient system resources exist to complete the API.
Change the Format of the Output
You can easily bold, italicize, or underlying your debugging output with the b, i, or u tags, respectively. For example:
DbgPrint(“<?dml?><b>API Failed!<b>\n”);
Gives:
3: kd> p
API Failed!
It’s also possible to color the output using the col tag:
<col fg=”Foreground Color” bg=”Background Color”>Text goes here</col>
Background and foreground colors are not specified by name. Instead, they’re specified indirectly by referencing the WinDbg settings chosen in the View->Options menu. A couple of the available settings is as follows (full settings can be found in the dml.doc supplied with the debugger):
Name |
Description |
changed | Color used by WinDbg for displaying values that have changed. Red by default |
subfg | Color used by WinDbg for subdued text. Light gray by default |
Putting these together, I can have the following statements:
DbgPrint("<?dml?> <col fg=\"changed\">API Failed!</col>\n"); DbgPrint("<?dml?> <col fg=\"subfg\">API Failed!</col>\n");
And get these results in the debugger:
3: kd> p
API Failed!
1: kd> p
API Failed!