Hi, I have a C++ program that uses ETW API and its code is as follows:
#define INITGUID // Include this #define to use SystemTraceControlGuid in Evntrace.h.
#include <windows.h>
#include <stdio.h>
#include <conio.h>
#include <strsafe.h>
#include <wmistr.h>
#include <evntrace.h>
#include <evntprov.h>
#include <vector>
#define LOGFILE_PATH L"mytrace.etl"
static bool EnableAdminPrivilege()
{
HANDLE token = NULL;
if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &token)) return false;
LUID luid;
if (!LookupPrivilegeValueW(NULL, SE_SYSTEM_PROFILE_NAME, &luid)) { CloseHandle(token); return false; }
TOKEN_PRIVILEGES tp;
tp.PrivilegeCount = 1;
tp.Privileges[0].Luid = luid;
tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
BOOL ok = AdjustTokenPrivileges(token, FALSE, &tp, sizeof(tp), NULL, NULL);
DWORD err = GetLastError();
CloseHandle(token);
return ok && (err == ERROR_SUCCESS);
}
static void foo()
{
for (int j = 0; j < 10; j++)
{
std::vector<int> v;
for (int i = 0; i < 10000000; i++)
{
v.push_back(i);
}
}
}
void wmain(void)
{
if (!EnableAdminPrivilege())
{
wprintf(L"Failed to enable admin privilege.\n");
return;
}
ULONG status = ERROR_SUCCESS;
TRACEHANDLE SessionHandle = 0;
EVENT_TRACE_PROPERTIES* pSessionProperties = NULL;
ULONG BufferSize = 0;
static const GUID ETW_PerfInfoGuid = { 0xce1dbfb4, 0x137e, 0x4da6, { 0x87, 0xb0, 0x3f, 0x59, 0xaa, 0x10, 0x2c, 0xbc } };
CLASSIC_EVENT_ID Events[] = { { ETW_PerfInfoGuid, 0x2e } };
// Allocate memory for the session properties. The memory must
// be large enough to include the log file name and session name,
// which get appended to the end of the session properties structure.
BufferSize = sizeof(EVENT_TRACE_PROPERTIES) + sizeof(LOGFILE_PATH) + sizeof(KERNEL_LOGGER_NAME) + 1024*1024*16;
pSessionProperties = (EVENT_TRACE_PROPERTIES*)malloc(BufferSize);
if (NULL == pSessionProperties)
{
wprintf(L"Unable to allocate %d bytes for properties structure.\n", BufferSize);
goto cleanup;
}
// Set the session properties. You only append the log file name
// to the properties structure; the StartTrace function appends
// the session name for you.
ZeroMemory(pSessionProperties, BufferSize);
pSessionProperties->Wnode.BufferSize = BufferSize;
pSessionProperties->Wnode.Flags = WNODE_FLAG_TRACED_GUID;
pSessionProperties->Wnode.ClientContext = 1; //QPC clock resolution
pSessionProperties->Wnode.Guid = SystemTraceControlGuid;
pSessionProperties->EnableFlags = EVENT_TRACE_FLAG_CSWITCH | EVENT_TRACE_FLAG_PROFILE | EVENT_TRACE_FLAG_PROCESS | EVENT_TRACE_FLAG_THREAD | EVENT_TRACE_FLAG_IMAGE_LOAD | EVENT_TRACE_TYPE_LOAD | EVENT_TRACE_FLAG_INTERRUPT | EVENT_TRACE_FLAG_SYSTEMCALL;
pSessionProperties->LogFileMode = EVENT_TRACE_FILE_MODE_CIRCULAR | EVENT_TRACE_SYSTEM_LOGGER_MODE;
pSessionProperties->MaximumFileSize = 1024; // 1024 MB
pSessionProperties->LoggerNameOffset = sizeof(EVENT_TRACE_PROPERTIES);
pSessionProperties->LogFileNameOffset = sizeof(EVENT_TRACE_PROPERTIES) + sizeof(KERNEL_LOGGER_NAME);
StringCbCopy((LPWSTR)((char*)pSessionProperties + pSessionProperties->LoggerNameOffset), sizeof(KERNEL_LOGGER_NAME), KERNEL_LOGGER_NAME);
StringCbCopy((LPWSTR)((char*)pSessionProperties + pSessionProperties->LogFileNameOffset), sizeof(LOGFILE_PATH), LOGFILE_PATH);
// Create the trace session.
status = StartTrace((PTRACEHANDLE)&SessionHandle, KERNEL_LOGGER_NAME, pSessionProperties);
if (ERROR_SUCCESS != status)
{
wprintf(L"StartTrace failed.\n");
goto cleanup;
}
status = TraceSetInformation(SessionHandle, TraceStackTracingInfo, Events, sizeof(Events));
if (ERROR_SUCCESS != status)
{
wprintf(L"TraceSetInformation failed.\n");
goto cleanup;
}
foo();
wprintf(L"Press any key to end trace session ");
_getch();
cleanup:
if (SessionHandle)
{
status = ControlTrace(SessionHandle, KERNEL_LOGGER_NAME, pSessionProperties, EVENT_TRACE_CONTROL_STOP);
if (ERROR_SUCCESS != status)
{
wprintf(L"ControlTrace(stop) failed with %lu\n", status);
}
}
if (pSessionProperties)
free(pSessionProperties);
}
However when analyzing the etl file this program generated, Stack column shows "Missing ImageId event".

I noticed there is a provider named "ImageId" in the etl file recorded by WPR.

The problem is how can I enable this provider programmatically?