I'm trying to figure out how can I include a WPP trace message in a macro.
Say, I'm using a vanilla WPP that is generated with the KMDF project. If I just do:
void func()
{
TraceEvents(TRACE_LEVEL_ERROR, TRACE_DEVICE, "irql=%d", KeGetCurrentIrql());
}
It compiles just fine.
But then if I put it in a macro:
#define IS_PASSIVE_LEVEL() \
if(KeGetCurrentIrql() != PASSIVE_LEVEL) \
{ \
TraceEvents(TRACE_LEVEL_ERROR, TRACE_DEVICE, "irql=%d", KeGetCurrentIrql()); \
ExRaiseStatus(STATUS_UNSUCCESSFUL); \
}
and then try using it:
void func()
{
IS_PASSIVE_LEVEL;
}
I'm getting an error:
Main.cpp(698,5): error C2065: 'TRACE_DEVICE': undeclared identifier
Main.cpp(698,5): error C3861: 'WPP_CALL_Main_cpp698': identifier not found
What am I doing wrong there?
WPP has its own preprocessor that runs before the C/C++ one and so you can't wrap the trace statements in macros (annoying but been a known issue since the beginning).
The backwards way to do this is to wrap the trace message call in WPP PRE and POST macros that do what you want. It's kind of painful to get right the first time but once you have it it's handy (e.g. we do this to log failed ASSERTs into the WPP Recorder in the release build). Your above behavior could be implemented with something like this:
#define WPP_CONTROL_GUIDS \
WPP_DEFINE_CONTROL_GUID( \
...
WPP_DEFINE_BIT(PASSIVE_ASSERTS) \
)
//
// begin_wpp config
//
// FUNC IS_PASSIVE_LEVEL{FLAG=PASSIVE_ASSERTS}();
//
// end_wpp
//
#define WPP_FLAG_PRE(PASSIVE_ASSERTS) \
do { \
if (KeGetCurrentIrql() != PASSIVE_LEVEL) {
#define WPP_FLAG_POST(PASSIVE_ASSERTS) \
/*DoTraceMessage*/; \
ExRaiseStatus(STATUS_UNSUCCESSFUL); \
} \
} while(0)
(That also might require some additional massaging and could possibly be simplified, I just threw it together for an example. WPP is always a bit finicky...)
1 Like
@Scott_Noone_OSR , thanks. But I'm still getting that same error. And yes. You bet, WPP is a finicky beast.
Let me show what I'm doing.
First off, I added your exact same declarations/definitions into the trace.h
file.
Then the definitions of WPP_FLAG_PRE
and WPP_FLAG_POST
went into the .h
file for the .cpp
file where I was intending to use them. (But then I also tried to place them into trace.h
. It didn't help.)
Finally I used those macros as such:
void func()
{
WPP_FLAG_PRE(PASSIVE_LEVEL_CHECK);
WPP_FLAG_POST(PASSIVE_LEVEL_CHECK);
}
And got these errors when compiling:
Main.cpp(3065,5): error C2065: 'TRACE_DEVICE': undeclared identifier|
|---|---|
Main.cpp(3065,5): error C3861: 'WPP_CALL_Main_cpp3065': identifier not found|
I'm still missing something.
PS. TRACE_DEVICE
came from:
TraceEvents(TRACE_LEVEL_ERROR, TRACE_DEVICE, "irql=%d", KeGetCurrentIrql());
that I placed inside your WPP_FLAG_POST
.
No, you call IS_PASSIVE_LEVEL() and not the macros themselves. This comment block is actually part of the WPP configuration:
//
// begin_wpp config
//
// FUNC IS_PASSIVE_LEVEL{FLAG=PASSIVE_ASSERTS}();
//
// end_wpp
//
You should see that function defined in your TMH with the pre/post macro contents emitted as part of it.
Yeah, it still doesn't work. I'm not sure what I'm doing wrong. This stuff is super confusing. Is there a working example somewhere, do you know?
What doesn't work? It doesn't compile? Or it compiles but you don't see the expected trace? Or something else?
Here's a diff patch that adds what I put here into the tracedrv sample. I didn't run it but it compiles and seems to emit the right code based on the assembly. (As I style thing I don't like the WPP macro raising a status, but that's not the question at the moment...)
Windows-driver-samples/general/tracing/tracedriver/tracedrv at main · microsoft/Windows-driver-samples
diff --git a/general/tracing/tracedriver/tracedrv/tracedrv.c b/general/tracing/tracedriver/tracedrv/tracedrv.c
index a1606f7b..0ca504bb 100644
--- a/general/tracing/tracedriver/tracedrv/tracedrv.c
+++ b/general/tracing/tracedriver/tracedrv/tracedrv.c
@@ -200,6 +200,9 @@ Return Value:
PAGED_CODE();
+ IS_PASSIVE_LEVEL();
+
+
IoCompleteRequest( Irp, IO_NO_INCREMENT );
return STATUS_SUCCESS;
}
diff --git a/general/tracing/tracedriver/tracedrv/tracedrv.h b/general/tracing/tracedriver/tracedrv/tracedrv.h
index 1b86834a..cae4b903 100644
--- a/general/tracing/tracedriver/tracedrv/tracedrv.h
+++ b/general/tracing/tracedriver/tracedrv/tracedrv.h
@@ -36,7 +36,8 @@ Environment:
#define WPP_CONTROL_GUIDS \
WPP_DEFINE_CONTROL_GUID(CtlGuid,(d58c126f, b309, 11d1, 969e, 0000f875a5bc), \
WPP_DEFINE_BIT(FLAG_ONE) \
- WPP_DEFINE_BIT(FLAG_TWO) )
+ WPP_DEFINE_BIT(FLAG_TWO) \
+ WPP_DEFINE_BIT(PASSIVE_ASSERTS) )
//
// DoTraceLevelMessage is a custom macro that adds support for levels to the
@@ -89,8 +90,19 @@ typedef enum _MachineState {
//USEPREFIX (TRACE_RETURN, "%!STDPREFIX!");
//FUNC TRACE_RETURN{FLAG=FLAG_ONE}(EXP);
//USESUFFIX (TRACE_RETURN, "Function Return=%!STATUS!",EXP);
+// FUNC IS_PASSIVE_LEVEL{FLAG=PASSIVE_ASSERTS}();
//end_wpp
+#define WPP_FLAG_PRE(PASSIVE_ASSERTS) \
+ do { \
+ if (KeGetCurrentIrql() != PASSIVE_LEVEL) {
+
+#define WPP_FLAG_POST(PASSIVE_ASSERTS) \
+ /*DoTraceMessage*/; \
+ ExRaiseStatus(STATUS_UNSUCCESSFUL); \
+ } \
+ } while(0)
+
//
// PRE macro: The name of the macro includes the condition arguments FLAGS and EXP
// define in FUNC above