Here is some code I use to enable and disable logging from my application.
It has been sanitized so I may not compile, let me know if you have
trouble…
#define MAX_STRLEN 255
#define MAX_SESSIONS 32
#define MY_EVENT_TRACING_SESSION_NAME L"MyDriver"
#define MY_EVENT_TRACING_LOGFILE_NAME L"MyDriver.etl"
typedef ULONG (*tStartTrace)(
OUT PTRACEHANDLE TraceHandle,
IN LPCWSTR InstanceName,
IN OUT PEVENT_TRACE_PROPERTIES Properties
);
typedef ULONG (*tStopTrace)(
IN TRACEHANDLE TraceHandle,
IN LPCWSTR InstanceName,
IN OUT PEVENT_TRACE_PROPERTIES Properties
);
typedef ULONG (*tQueryTrace)(
IN TRACEHANDLE TraceHandle,
IN LPCWSTR InstanceName,
IN OUT PEVENT_TRACE_PROPERTIES Properties
);
typedef ULONG (*tControlTrace)(
IN TRACEHANDLE TraceHandle,
IN LPCWSTR InstanceName,
IN OUT PEVENT_TRACE_PROPERTIES Properties,
IN ULONG ControlCode
);
typedef ULONG (*tEnableTrace)(
IN ULONG Enable,
IN ULONG EnableFlag,
IN ULONG EnableLevel,
IN LPCGUID ControlGuid,
IN TRACEHANDLE TraceHandle
);
typedef ULONG (*tQueryAllTraces)(
OUT PEVENT_TRACE_PROPERTIES *PropertyArray,
IN ULONG PropertyArrayCount,
OUT PULONG LoggerCount
);
tStartTrace pStartTrace=NULL;
tStopTrace pStopTrace=NULL;
tQueryTrace pQueryTrace=NULL;
tControlTrace pControlTrace=NULL;
tEnableTrace pEnableTrace=NULL;
tQueryAllTraces pQueryAllTraces=NULL;
BOOLEAN DoImports( void )
{
if(!pStartTrace) {
pStartTrace =
(tStartTrace)GetProcAddress(GetModuleHandle(TEXT(“advapi32”)),“StartTraceW”)
;
pStopTrace =
(tStopTrace)GetProcAddress(GetModuleHandle(TEXT(“advapi32”)),“StopTraceW”);
pQueryTrace =
(tQueryTrace)GetProcAddress(GetModuleHandle(TEXT(“advapi32”)),“QueryTraceW”)
;
pControlTrace =
(tControlTrace)GetProcAddress(GetModuleHandle(TEXT(“advapi32”)),“ControlTrac
eW”);
pEnableTrace =
(tEnableTrace)GetProcAddress(GetModuleHandle(TEXT(“advapi32”)),“EnableTrace”
);
pQueryAllTraces =
(tQueryAllTraces)GetProcAddress(GetModuleHandle(TEXT(“advapi32”)),“QueryAllT
racesW”);
if(pStartTrace) {
return TRUE;
}
return FALSE;
} else {
return TRUE;
}
}
ULONG GetRegistryDword_global (
const WCHAR * ValueName,
ULONG DefaultValue )
{
ULONG Err=0;
HKEY Key = INVALID_HANDLE_VALUE;
const WCHAR *RegPath =
L"SYSTEM\CurrentControlSet\Services\MyDriver\";
ULONG Value = DefaultValue;
Err = RegOpenKeyExW (
HKEY_LOCAL_MACHINE,
RegPath,
0,
KEY_READ,
&Key );
if ( Err == 0 ) {
ULONG TempValue = 0;
ULONG DataSize = sizeof(TempValue);
Err = RegQueryValueExW (
Key,
ValueName,
NULL, // reserved
NULL, // address of buffer for value type
(char*)(&TempValue),
&DataSize );
if ( Err == 0 ) {
Value = TempValue;
}
RegCloseKey(Key);
Key = INVALID_HANDLE_VALUE;
} else {
DEBUG_WRITE(L">>> GetRegistryDword: error %08x opening
‘%s’\n",RegPath);
}
return Value;
}
PEVENT_TRACE_PROPERTIES AllocSessionProperties()
{
PEVENT_TRACE_PROPERTIES Properties;
ULONG SizeNeeded;
// Calculate the size needed to store the properties,
// a LogFileName string, and LoggerName string.
SizeNeeded = sizeof(EVENT_TRACE_PROPERTIES) +
(2 * MAX_STRLEN * sizeof(WCHAR));
Properties = (PEVENT_TRACE_PROPERTIES) malloc(SizeNeeded);
if ( Properties == NULL ) {
SetLastError(ERROR_OUTOFMEMORY);
return NULL;
}
ZeroMemory( Properties, SizeNeeded );
// Set the location for the event tracing session name.
// LoggerNameOffset is a relative address.
Properties->LoggerNameOffset = sizeof(EVENT_TRACE_PROPERTIES);
// Set the log file name location.
// LogFileNameOffset is a relative address.
Properties->LogFileNameOffset = sizeof(EVENT_TRACE_PROPERTIES) +
(MAX_STRLEN * sizeof(WCHAR));
// Store the total number of bytes pointed to by Properties.
Properties->Wnode.BufferSize = SizeNeeded;
// The WNODE_HEADER is being used.
Properties->Wnode.Flags = WNODE_FLAG_TRACED_GUID;
RtlCopyMemory(&Properties->Wnode.Guid,&MY_DRIVER_WPP_GUID,sizeof(GUID));
DEBUG_WRITE(L"Size = %d\n",SizeNeeded);
return Properties;
}
ULONG EnableProvider(TRACEHANDLE SessionHandle)
{
if(DoImports()) {
ULONG ret;
ULONG DebugLevel =
GetRegistryDword_global(L"DebugLevel",0x0fffffff);
ret = pEnableTrace (
(ULONG)TRUE, // True = enable; FALSE = disable.
DebugLevel, // Flag.
0, // Level.
&MY_DRIVER_WPP_GUID, // Provider to enable.
SessionHandle); // Identifies the session.
wprintf(L"enable = %08x\n",ret);
return ret;
} else {
return 0xffffffff;
}
}
ULONG DisableProvider(TRACEHANDLE SessionHandle)
{
if(DoImports()) {
ULONG ret;
ret = pEnableTrace (
(ULONG)FALSE,//True = enable; FALSE = disable.
0, // Flag.
0, // Level.
&MY_DRIVER_WPP_GUID, // Provider to enable.
SessionHandle); // Identifies the session.
return ret;
} else {
return 0xffffffff;
}
}
ULONG StopMySession(TRACEHANDLE MyHandle)
{
if(DoImports()) {
ULONG ret;
PEVENT_TRACE_PROPERTIES Properties;
Properties = AllocSessionProperties();
if ( Properties == NULL ) {
return(ERROR_OUTOFMEMORY);
}
if(MyHandle == (TRACEHANDLE)INVALID_HANDLE_VALUE) {
DEBUG_WRITE(L"Stopping via session name\n");
ret = pControlTrace (MyHandle, MY_EVENT_TRACING_SESSION_NAME,
Properties, EVENT_TRACE_CONTROL_STOP);
} else {
DEBUG_WRITE(L"Stopping via session properties\n");
ret = pControlTrace (MyHandle, NULL, Properties,
EVENT_TRACE_CONTROL_STOP);
}
if ( ret == ERROR_SUCCESS ) {
wprintf(L"\n\n Stopped…\n");
PrintSession(Properties);
} else {
wprintf(L"\nError %08x stopping\n",ret);
}
free(Properties);
return ret;
} else {
return 0xffffffff;
}
}
TRACEHANDLE StartMySession()
{
if(DoImports()) {
ULONG ret;
PEVENT_TRACE_PROPERTIES Properties;
TRACEHANDLE SessionHandle=(TRACEHANDLE)INVALID_HANDLE_VALUE;
Properties = AllocSessionProperties();
if ( Properties == NULL ) {
return((TRACEHANDLE) INVALID_HANDLE_VALUE);
}
if(GetRegistryDword_global(L"DebugLogCircular",1)) {
// Deliver events to a circular log file.
Properties->LogFileMode |= EVENT_TRACE_FILE_MODE_CIRCULAR ;
}
// Circular log files should have a maximum size.
Properties->MaximumFileSize =
GetRegistryDword_global(L"DebugLogMaxSize",20);
// with just the file name it will store it in the current
directory.
//wcscpy(EventTracingFile,MY_EVENT_TRACING_LOGFILE_NAME);
GetSSPath(EventTracingFile,sizeof(EventTracingFile)/sizeof(WCHAR));
wcscat(EventTracingFile,MY_EVENT_TRACING_LOGFILE_NAME);
// Store the name of the log file.
wcscpy ((LPWSTR) ((char *)Properties +
Properties->LogFileNameOffset), EventTracingFile);
// Choose some buffer settings.
Properties->BufferSize =
GetRegistryDword_global(L"DebugLogBufferSize",4);
Properties->MinimumBuffers =
GetRegistryDword_global(L"DebugLogMinBuffers",3);
Properties->MaximumBuffers =
GetRegistryDword_global(L"DebugLogMaxBuffers",6);
// Start the session.
ret = pStartTrace (&SessionHandle,
MY_EVENT_TRACING_SESSION_NAME,
Properties);
if ( ret!= ERROR_SUCCESS ) {
wprintf(L"StartTrace failed: %d\n", ret);
PrintWin32Error(ret);
PrintSession(Properties);
SessionHandle = (TRACEHANDLE) INVALID_HANDLE_VALUE;
} else {
PrintSession(Properties);
EnableProvider(SessionHandle);
//QueryAll();
}
free(Properties);
return SessionHandle;
} else {
return (TRACEHANDLE)NULL;
}
}
Thanks,
Rob
-----Original Message-----
From: xxxxx@lists.osr.com [mailto:bounce-167589-
xxxxx@lists.osr.com] On Behalf Of Mark Roddy
Sent: Monday, February 16, 2004 7:14 PM
To: Windows System Software Devs Interest List
Subject: RE: [ntdev] ETW and debug prints
For instance I modified the example henry provided so that I have an
‘always
log’ level independent of the flags that are set:
#define WPP_LEVEL_FLAGS_ENABLED(lvl, flags) \
(WPP_CONTROL(WPP_BIT_ ## flags).Level == GENSHELL_DEBUG_ALWAYS) || \
((WPP_LEVEL_ENABLED(flags) && \
(WPP_CONTROL(WPP_BIT_ ## flags).Level >= lvl)))
This compiles (at the moment I have no idea if it works,) but the
mechanism
appears to be fairly straight-forward (although undocumented of course)
and
flexible enough to accommodate more complex schemes. There is probably
some
way to work your level-per-component scheme into this.
Now my problem is that I can control the trace flags from the traceview
application, but I have to set the levels from my own interface. That
bites
from a usability perspective, but unless I am missing yet another
undocumented feature (which would of course be just about all of the ETW
features) I think I am stuck with this.
> -----Original Message-----
> From: xxxxx@lists.osr.com
> [mailto:xxxxx@lists.osr.com] On Behalf Of Ian Service
> Sent: Monday, February 16, 2004 6:21 PM
> To: Windows System Software Devs Interest List
> Subject: RE: [ntdev] ETW and debug prints
>
>
>
> >currently we’re using debug areas and every area has assigned debug
> >level (as trace, warning, error). One application/driver usually
> uses
> >several areas.
>
> Well one thing we tried to do was to be a flexible as
> possible here to incorporate multiple different models.
> However we tend to steer new implementations towards the
> levels model because of its straightforwardness.
>
> It is also convenient to have a common concept so that
> support organizations can straightforwardly turn on tracing
> for mixed components together.
>
> However sometimes that’s not what is wanted.
>
> I think the most common thing that is done is to define flags
> and levels together and adjust the macros appropriately.This
> is the sort of example that Mark was trying to achieve at the
> start of this discussion. You can override the macros to have
> there own meaning of what LEVEL and FLAGS really are in your case.
>
>
>
> -----Original Message-----
> From: xxxxx@lists.osr.com
> [mailto:xxxxx@lists.osr.com] On Behalf Of Michal Vodicka
> Sent: Monday, February 16, 2004 3:08 PM
> To: Windows System Software Devs Interest List
> Subject: RE: [ntdev] ETW and debug prints
>
> > ----------
> > From:
> > xxxxx@windows.microsoft.com[SMTP:xxxxx@windows.microsoft.com]
> > Reply To: xxxxx@lists.osr.com
> > Sent: Monday, February 16, 2004 11:32 PM
> > To: xxxxx@lists.osr.com
> > Subject: RE: [ntdev] ETW and debug prints
> >
> > >Sorry, I presumed it is obvious. They capture kernel DbgPrint and
> user
> > mode
> > >OutputDebugPrint and display them.
> > Well OK I do know the obvious :-), but I don’t know if there is
> > anywhere they could call for example Traceprt.
> >
> Ah so. Probably not; SoftICE can call a KD extension but I
> guess it isn’t sufficient.
>
> Thanks for answers, it seems I’ll have to try it to see more. The last
> question: currently we’re using debug areas and every area
> has assigned debug level (as trace, warning, error). One
> application/driver usually uses several areas. ETW seems to
> use bit flags and one level which is global for all. How to
> map our approach to it? I see two possibilities – use one
> GUID per area and use level only or reserve 3 bits/flags per
> area and express level as value of these bits. I’m not sure
> if the second is even possible with ETW macros. Any other
> possibility? And are there any non-obvious consequences?
>
> Best regards,
>
> Michal Vodicka
> STMicroelectronics Design and Application s.r.o.
> [michal.vodicka@st.com, http:://www.st.com]
>
>
> —
> Questions? First check the Kernel Driver FAQ at
> http://www.osronline.com/article.cfm?id=256
>
> You are currently subscribed to ntdev as:
> xxxxx@windows.microsoft.com To unsubscribe send a blank
> email to xxxxx@lists.osr.com
>
> —
> Questions? First check the Kernel Driver FAQ at
> http://www.osronline.com/article.cfm?id=256
>
> You are currently subscribed to ntdev as:
> xxxxx@hollistech.com To unsubscribe send a blank email to
> xxxxx@lists.osr.com
>
Questions? First check the Kernel Driver FAQ at
http://www.osronline.com/article.cfm?id=256
You are currently subscribed to ntdev as: xxxxx@cdp.com
To unsubscribe send a blank email to xxxxx@lists.osr.com