683 lines
19 KiB
C++
683 lines
19 KiB
C++
#define _UNICODE
|
|
#define UNICODE
|
|
|
|
#include <nt.h>
|
|
#include <ntrtl.h>
|
|
#include <nturtl.h>
|
|
#include <windows.h>
|
|
#include <stdio.h>
|
|
|
|
#pragma warning(disable: 4201) // error C4201: nonstandard extension used : nameless struct/union
|
|
#include <wmistr.h>
|
|
#include <evntrace.h>
|
|
#include <guiddef.h>
|
|
|
|
#define REG_TRACE_REGKEY TEXT("SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Tracing")
|
|
|
|
#define REG_TRACE_ENABLED TEXT("EnableTracing")
|
|
|
|
#define REG_TRACE_LOG_FILE_NAME TEXT("LogFileName")
|
|
#define REG_TRACE_LOG_SESSION_NAME TEXT("LogSessionName")
|
|
#define REG_TRACE_LOG_BUFFER_SIZE TEXT("BufferSize")
|
|
#define REG_TRACE_LOG_MIN_BUFFERS TEXT("MinBuffers")
|
|
#define REG_TRACE_LOG_MAX_BUFFERS TEXT("MaxBuffers")
|
|
#define REG_TRACE_LOG_MAX_FILESIZE TEXT("MaxFileSize")
|
|
#define REG_TRACE_LOG_MAX_HISTORY TEXT("MaxHistorySize")
|
|
#define REG_TRACE_LOG_MAX_BACKUPS TEXT("MaxBackups")
|
|
|
|
#define REG_TRACE_ACTIVE TEXT("Active")
|
|
#define REG_TRACE_CONTROL TEXT("ControlFlags")
|
|
#define REG_TRACE_LEVEL TEXT("Level")
|
|
#define REG_TRACE_GUID TEXT("Guid")
|
|
|
|
#include "wmlum.h"
|
|
|
|
#ifndef ARRAYSIZE
|
|
#define ARRAYSIZE(x) (sizeof(x)/sizeof(*(x)))
|
|
#endif
|
|
|
|
VOID RegisterIfNecessary(LPWSTR KeyName, LPCGUID Guid);
|
|
|
|
WMILIBPRINTFUNC WmiLibPrint = 0;
|
|
|
|
#define NT_LOGGER L"NT Kernel Logger"
|
|
|
|
VOID
|
|
MyDbgPrint(
|
|
UINT Level,
|
|
PCHAR FormatString,
|
|
...
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Prints a message to the debugger or console, as appropriate.
|
|
|
|
Arguments:
|
|
|
|
String - The initial message string to print.
|
|
|
|
Any FormatMessage-compatible arguments to be inserted in the
|
|
ErrorMessage before it is logged.
|
|
|
|
Return Value:
|
|
None.
|
|
|
|
--*/
|
|
{
|
|
CHAR Buffer[256];
|
|
DWORD Bytes;
|
|
va_list ArgList;
|
|
|
|
if (WmiLibPrint == NULL) {
|
|
return;
|
|
}
|
|
|
|
va_start(ArgList, FormatString);
|
|
|
|
Bytes = FormatMessageA(FORMAT_MESSAGE_FROM_STRING,
|
|
FormatString,
|
|
0,
|
|
0,
|
|
Buffer,
|
|
sizeof(Buffer) / sizeof(CHAR),
|
|
&ArgList);
|
|
|
|
|
|
va_end(ArgList);
|
|
if (Bytes != 0) {
|
|
(*WmiLibPrint)(Level, Buffer);
|
|
}
|
|
}
|
|
|
|
UINT HexVal(int ch) { return isdigit(ch) ? ch - '0' : ch - 'a' + 10; }
|
|
UINT Hex(LPWSTR s, int n)
|
|
{
|
|
UINT res = 0;
|
|
while(n--) { res = res * 16 + HexVal(*s++); }
|
|
return res;
|
|
}
|
|
|
|
VOID
|
|
GuidFromStr(
|
|
IN LPWSTR str,
|
|
OUT LPGUID guid)
|
|
{
|
|
guid->Data1 = Hex(str + 0, 8);
|
|
guid->Data2 = (USHORT)Hex(str + 9, 4);
|
|
guid->Data3 = (USHORT)Hex(str + 14, 4);
|
|
guid->Data4[0] = (UCHAR) Hex(str + 19, 2);
|
|
guid->Data4[1] = (UCHAR) Hex(str + 21, 2);
|
|
guid->Data4[2] = (UCHAR) Hex(str + 24, 2);
|
|
guid->Data4[3] = (UCHAR) Hex(str + 26, 2);
|
|
guid->Data4[4] = (UCHAR) Hex(str + 28, 2);
|
|
guid->Data4[5] = (UCHAR) Hex(str + 30, 2);
|
|
guid->Data4[6] = (UCHAR) Hex(str + 32, 2);
|
|
guid->Data4[7] = (UCHAR) Hex(str + 34, 2);
|
|
}
|
|
|
|
typedef struct _INHERITED_DATA {
|
|
BOOL Active;
|
|
ULONG ControlFlags;
|
|
ULONG LogLevel;
|
|
ULONG Reserved;
|
|
TRACEHANDLE Logger;
|
|
GUID Guid;
|
|
BOOL GuidDefined;
|
|
} INHERITED_DATA, *PINHERITED_DATA;
|
|
|
|
VOID
|
|
ReadCommonData(
|
|
IN HKEY hk,
|
|
IN OUT PINHERITED_DATA data
|
|
)
|
|
{
|
|
ULONG ulTemp;
|
|
ULONG dwSize;
|
|
WCHAR szGuid[16 * 3 + 1];
|
|
|
|
dwSize = sizeof(ulTemp);
|
|
if (ERROR_SUCCESS == RegQueryValueEx(hk, REG_TRACE_ACTIVE,
|
|
NULL, NULL, (BYTE *) &ulTemp, &dwSize))
|
|
{
|
|
data->Active = ulTemp;
|
|
}
|
|
|
|
dwSize = sizeof(ulTemp);
|
|
if (ERROR_SUCCESS == RegQueryValueEx(hk, REG_TRACE_CONTROL,
|
|
NULL, NULL,
|
|
(BYTE *) &ulTemp, &dwSize))
|
|
{
|
|
data->ControlFlags = ulTemp;
|
|
}
|
|
|
|
|
|
dwSize = sizeof(ulTemp);
|
|
if (ERROR_SUCCESS == RegQueryValueEx(hk, REG_TRACE_LEVEL,
|
|
NULL, NULL,
|
|
(BYTE *) &ulTemp,
|
|
&dwSize))
|
|
{
|
|
data->LogLevel = ulTemp;
|
|
}
|
|
|
|
dwSize = sizeof(szGuid);
|
|
if (ERROR_SUCCESS == RegQueryValueEx(hk, REG_TRACE_GUID,
|
|
NULL, NULL,
|
|
(BYTE *) &szGuid,
|
|
&dwSize))
|
|
{
|
|
GuidFromStr(szGuid, &data->Guid);
|
|
data->GuidDefined = TRUE;
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
typedef struct _FULL_LOGGER_INFO {
|
|
EVENT_TRACE_PROPERTIES LoggerInfo;
|
|
WCHAR logFileName[MAX_PATH + 512];
|
|
WCHAR logSessionName[MAX_PATH + 512];
|
|
ULONG MaxHistorySize;
|
|
ULONG MaxBackups;
|
|
} FULL_LOGGER_INFO, *PFULL_LOGGER_INFO;
|
|
|
|
GUID MySystemTraceControlGuid = { /* 9e814aad-3204-11d2-9a82-006008a86939 */
|
|
0x9e814aad,
|
|
0x3204,
|
|
0x11d2,
|
|
{0x9a, 0x82, 0x00, 0x60, 0x08, 0xa8, 0x69, 0x39}
|
|
};
|
|
|
|
|
|
VOID
|
|
ReadLoggerInfo(
|
|
IN HKEY hk,
|
|
OUT PTRACEHANDLE Logger)
|
|
{
|
|
FULL_LOGGER_INFO x;
|
|
WCHAR tmpName[MAX_PATH + 512];
|
|
WCHAR tmpName2[MAX_PATH + 512];
|
|
ULONG ulTemp;
|
|
ULONG dwReadSize = sizeof(ulTemp);
|
|
ULONG status;
|
|
SYSTEMTIME localTime;
|
|
BOOL success;
|
|
|
|
RtlZeroMemory(&x.LoggerInfo, sizeof(x));
|
|
x.LoggerInfo.Wnode.BufferSize = sizeof(x);
|
|
x.LoggerInfo.Wnode.Flags = WNODE_FLAG_TRACED_GUID;
|
|
x.LoggerInfo.LogFileNameOffset = (ULONG)((ULONG_PTR)x.logFileName - (ULONG_PTR)&x);
|
|
x.LoggerInfo.LoggerNameOffset = (ULONG)((ULONG_PTR)x.logSessionName - (ULONG_PTR)&x);
|
|
x.LoggerInfo.LogFileMode = EVENT_TRACE_FILE_MODE_CIRCULAR;
|
|
|
|
//
|
|
// If the key describes a logger,
|
|
// it should have at least LOG_SESSION_NAME value
|
|
//
|
|
dwReadSize = sizeof(x.logSessionName);
|
|
status = RegQueryValueEx(hk, REG_TRACE_LOG_SESSION_NAME,
|
|
NULL, NULL,
|
|
(BYTE *) &x.logSessionName, &dwReadSize);
|
|
if (status != ERROR_SUCCESS) {
|
|
return;
|
|
}
|
|
|
|
if ( wcscmp(x.logSessionName, NT_LOGGER) == 0) {
|
|
MyDbgPrint(3,"[WMILIB] Enabling system tracing\n",
|
|
x.logSessionName,
|
|
x.LoggerInfo.Wnode.HistoricalContext);
|
|
|
|
x.LoggerInfo.Wnode.Guid = MySystemTraceControlGuid;
|
|
x.LoggerInfo.EnableFlags |=
|
|
EVENT_TRACE_FLAG_PROCESS |
|
|
EVENT_TRACE_FLAG_THREAD |
|
|
EVENT_TRACE_FLAG_DISK_IO |
|
|
EVENT_TRACE_FLAG_NETWORK_TCPIP |
|
|
EVENT_TRACE_FLAG_REGISTRY;
|
|
}
|
|
|
|
// Let's query, whether there is a logger with this name
|
|
status = QueryTrace(0, x.logSessionName, &x.LoggerInfo);
|
|
if (ERROR_SUCCESS == status) {
|
|
MyDbgPrint(1,"[WMILIB] Query successful Logger %1!ws! %2!08X!:%3!08X!\n",
|
|
x.logSessionName,
|
|
x.LoggerInfo.Wnode.HistoricalContext);
|
|
*Logger = x.LoggerInfo.Wnode.HistoricalContext;
|
|
return;
|
|
}
|
|
|
|
if (ERROR_WMI_INSTANCE_NOT_FOUND != status) {
|
|
MyDbgPrint(1,"[WMILIB] Query of %1!ws! failed %2!d!\n",
|
|
x.logSessionName, status);
|
|
}
|
|
|
|
// There is no logger runing
|
|
|
|
// First, We will query logFileName value into tmpName variable
|
|
// and then expand it into logFileName
|
|
dwReadSize = sizeof(tmpName);
|
|
status = RegQueryValueEx(hk, REG_TRACE_LOG_FILE_NAME,
|
|
NULL, NULL,
|
|
(BYTE *) &tmpName, &dwReadSize);
|
|
if (status != ERROR_SUCCESS) {
|
|
// If there is no logFileName, then this node doesn't describe
|
|
// a logger. Bail out.
|
|
MyDbgPrint(1,"[WMILIB] Cannot read log file name, status %1!d!\n", status);
|
|
return;
|
|
}
|
|
dwReadSize = ExpandEnvironmentStrings(tmpName, x.logFileName, ARRAYSIZE(x.logFileName) );
|
|
if (dwReadSize == 0 || dwReadSize > ARRAYSIZE(x.logFileName)) {
|
|
MyDbgPrint(1,"[WMILIB] Expansion of %1!ws! failed, return value %2!d!\n", tmpName, dwReadSize);
|
|
CopyMemory(x.logFileName, tmpName, sizeof(x.logFileName));
|
|
}
|
|
|
|
MyDbgPrint(3,"[WMILIB] FileName %1!S!\n", x.logFileName);
|
|
MyDbgPrint(3,"[WMILIB] Session %1!S!\n", x.logSessionName);
|
|
|
|
dwReadSize = sizeof(ulTemp);
|
|
if (ERROR_SUCCESS == RegQueryValueEx(hk, REG_TRACE_LOG_BUFFER_SIZE,
|
|
NULL, NULL,
|
|
(BYTE *) &ulTemp, &dwReadSize))
|
|
x.LoggerInfo.BufferSize = ulTemp;
|
|
|
|
dwReadSize = sizeof(ulTemp);
|
|
if (ERROR_SUCCESS == RegQueryValueEx(hk, REG_TRACE_LOG_MIN_BUFFERS,
|
|
NULL, NULL,
|
|
(BYTE *) &ulTemp, &dwReadSize))
|
|
x.LoggerInfo.MinimumBuffers = ulTemp;
|
|
|
|
dwReadSize = sizeof(ulTemp);
|
|
if (ERROR_SUCCESS == RegQueryValueEx(hk, REG_TRACE_LOG_MAX_BUFFERS,
|
|
NULL, NULL,
|
|
(BYTE *) &ulTemp, &dwReadSize))
|
|
x.LoggerInfo.MaximumBuffers = ulTemp;
|
|
|
|
dwReadSize = sizeof(ulTemp);
|
|
if (ERROR_SUCCESS == RegQueryValueEx(hk, REG_TRACE_LOG_MAX_FILESIZE,
|
|
NULL, NULL,
|
|
(BYTE *) &ulTemp, &dwReadSize))
|
|
x.LoggerInfo.MaximumFileSize = ulTemp;
|
|
|
|
x.MaxHistorySize = 4 * x.LoggerInfo.MaximumFileSize;
|
|
dwReadSize = sizeof(ulTemp);
|
|
if (ERROR_SUCCESS == RegQueryValueEx(hk, REG_TRACE_LOG_MAX_HISTORY,
|
|
NULL, NULL,
|
|
(BYTE *) &ulTemp, &dwReadSize))
|
|
x.MaxHistorySize = ulTemp;
|
|
|
|
dwReadSize = sizeof(ulTemp);
|
|
if (ERROR_SUCCESS == RegQueryValueEx(hk, REG_TRACE_LOG_MAX_BACKUPS,
|
|
NULL, NULL,
|
|
(BYTE *) &ulTemp, &dwReadSize))
|
|
x.MaxBackups = ulTemp;
|
|
|
|
|
|
if (x.MaxBackups == 0) {
|
|
// We need to check whether the file already exist and rename it //
|
|
|
|
GetLocalTime(&localTime);
|
|
_snwprintf(tmpName, ARRAYSIZE(tmpName),
|
|
L"%1ws.%04d%02d%02d%02d%02d%02d",
|
|
x.logFileName,
|
|
localTime.wYear,localTime.wMonth,localTime.wDay,
|
|
localTime.wHour,localTime.wMinute,localTime.wSecond);
|
|
|
|
success = MoveFile(x.logFileName, tmpName);
|
|
if (!success) {
|
|
status = GetLastError();
|
|
} else {
|
|
status = ERROR_SUCCESS;
|
|
}
|
|
MyDbgPrint(3,"[WMILIB] Rename %1!ws! => %2!ws!, status %3!d!\n",
|
|
x.logFileName, tmpName, status);
|
|
} else {
|
|
int i;
|
|
for (i = x.MaxBackups; i >= 1; --i) {
|
|
_snwprintf(tmpName2, ARRAYSIZE(tmpName),
|
|
L"%1ws.%03d",
|
|
x.logFileName, i);
|
|
if (i == 1) {
|
|
wcscpy(tmpName, x.logFileName);
|
|
} else {
|
|
_snwprintf(tmpName, ARRAYSIZE(tmpName),
|
|
L"%1ws.%03d",
|
|
x.logFileName, i-1);
|
|
}
|
|
success = MoveFileEx(tmpName, tmpName2, MOVEFILE_REPLACE_EXISTING);
|
|
if (!success) {
|
|
status = GetLastError();
|
|
} else {
|
|
status = ERROR_SUCCESS;
|
|
}
|
|
MyDbgPrint(3,"[WMILIB] Rename %1!ws! => %2!ws!, status %3!d!\n",
|
|
tmpName, tmpName2, status);
|
|
}
|
|
}
|
|
|
|
status = StartTrace(Logger, x.logSessionName, &x.LoggerInfo);
|
|
*Logger = x.LoggerInfo.Wnode.HistoricalContext;
|
|
MyDbgPrint(1,"[WMILIB] Logger %1!ws! started %3!08X!:%4!08X! %2!d!\n",
|
|
x.logSessionName, status, *Logger);
|
|
}
|
|
|
|
WCHAR szModuleName[MAX_PATH+500];
|
|
|
|
ULONG
|
|
InitWmiInternal(
|
|
IN HKEY Dir OPTIONAL, // if 0, then current ...
|
|
IN LPWSTR ProductName,
|
|
IN PINHERITED_DATA InheritedData OPTIONAL
|
|
)
|
|
{
|
|
ULONG status;
|
|
INHERITED_DATA data;
|
|
HKEY CloseMe = 0;
|
|
HKEY hk = 0;
|
|
//ULONG ulTemp;
|
|
//ULONG dwReadSize = sizeof(ulTemp);
|
|
DWORD dwSizeOfModuleName;
|
|
DWORD dwIndex;
|
|
|
|
MyDbgPrint(2, "[WMILIB] Init %1!ws!\n", ProductName);
|
|
|
|
if (InheritedData) {
|
|
data = *InheritedData;
|
|
} else {
|
|
ZeroMemory(&data, sizeof(data));
|
|
}
|
|
data.GuidDefined = FALSE;
|
|
|
|
if (!Dir) {
|
|
status = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
|
|
REG_TRACE_REGKEY,
|
|
0,
|
|
KEY_READ,
|
|
&CloseMe);
|
|
if (status != ERROR_SUCCESS) {
|
|
MyDbgPrint(1,"[WMILIB] Failed to open Trace Key, %1!d!\n", status);
|
|
goto exit_gracefully;
|
|
}
|
|
Dir = CloseMe;
|
|
}
|
|
|
|
status = RegOpenKeyEx(Dir,
|
|
ProductName,
|
|
0,
|
|
KEY_READ,
|
|
&hk);
|
|
if (status != ERROR_SUCCESS) {
|
|
MyDbgPrint(1,"[WMILIB] Failed to open %1!ws! subkey, %2!d!\n", ProductName, status);
|
|
goto exit_gracefully;
|
|
}
|
|
|
|
|
|
ReadLoggerInfo(hk, &data.Logger);
|
|
ReadCommonData(hk, &data);
|
|
|
|
if (!data.Active) {
|
|
MyDbgPrint(1,"[WMILIB] Tracing is not active for %1!ws!\n", ProductName);
|
|
goto exit_gracefully;
|
|
}
|
|
|
|
if (data.GuidDefined) {
|
|
// First, try to find its in the map. //
|
|
// If it is there, we need to register this Guid //
|
|
RegisterIfNecessary(ProductName, &data.Guid);
|
|
|
|
// We can try to start tracing //
|
|
if (data.Logger) {
|
|
status = EnableTrace(data.Active,
|
|
data.ControlFlags,
|
|
data.LogLevel,
|
|
&data.Guid,
|
|
data.Logger);
|
|
MyDbgPrint(1,"[WMILIB] Enable=%1!d! %2!ws!, status %3!d!\n", data.
|
|
Active, ProductName, status);
|
|
}
|
|
}
|
|
|
|
dwSizeOfModuleName = sizeof(szModuleName);
|
|
dwIndex = 0;
|
|
while (ERROR_SUCCESS == (status = RegEnumKeyEx(hk, dwIndex,
|
|
szModuleName,
|
|
&dwSizeOfModuleName,
|
|
NULL, NULL, NULL, NULL)))
|
|
{
|
|
InitWmiInternal(hk, szModuleName, &data);
|
|
|
|
dwSizeOfModuleName = sizeof(szModuleName);
|
|
++dwIndex;
|
|
}
|
|
|
|
if (ERROR_NO_MORE_ITEMS == status) {
|
|
status = ERROR_SUCCESS;
|
|
}
|
|
|
|
exit_gracefully:
|
|
if (CloseMe) {
|
|
RegCloseKey(CloseMe);
|
|
}
|
|
if (hk) {
|
|
RegCloseKey(hk);
|
|
}
|
|
return status;
|
|
}
|
|
|
|
ULONG
|
|
InitWmi(
|
|
IN LPWSTR ProductName
|
|
)
|
|
{
|
|
MyDbgPrint(1, "[WMILIB] Initialize %1!ws!\n", ProductName);
|
|
return InitWmiInternal(0, ProductName, 0);
|
|
}
|
|
|
|
#pragma warning(disable: 4512) // error C4512: 'blah-blah-blah' : assignment operator could not be generated
|
|
#pragma warning(disable: 4100) // '_P' : unreferenced formal parameter
|
|
#include <xmemory>
|
|
#pragma warning(default: 4100)
|
|
#include <map>
|
|
//#include <xstring>
|
|
|
|
struct wless {
|
|
bool operator() (LPCWSTR a, LPCWSTR b) const { return lstrcmpW(a,b) < 0; }
|
|
};
|
|
|
|
typedef std::map<LPCWSTR, PWMILIB_REG_STRUCT, wless > WIDE_STRING_MAP;
|
|
|
|
WIDE_STRING_MAP* map;
|
|
PWMILIB_REG_STRUCT head;
|
|
|
|
ULONG
|
|
WmilibControlCallback(
|
|
IN WMIDPREQUESTCODE RequestCode,
|
|
IN PVOID Context,
|
|
IN OUT ULONG *InOutBufferSize,
|
|
IN OUT PVOID Buffer
|
|
)
|
|
{
|
|
PWMILIB_REG_STRUCT Ctx = (PWMILIB_REG_STRUCT)Context;
|
|
ULONG Status = ERROR_SUCCESS;
|
|
|
|
switch (RequestCode)
|
|
{
|
|
case WMI_ENABLE_EVENTS:
|
|
{
|
|
Ctx->LoggerHandle = GetTraceLoggerHandle( Buffer );
|
|
Ctx->EnableLevel = GetTraceEnableLevel(Ctx->LoggerHandle);
|
|
Ctx->EnableFlags = GetTraceEnableFlags(Ctx->LoggerHandle);
|
|
MyDbgPrint(3, "[WMILIB] WMI_ENABLE_EVENTS Ctx 0x%1!08X! Flags %2!X! Lev %3!d! Logger %4!08X!:%5!08X!\n",
|
|
Ctx, Ctx->EnableFlags, Ctx->EnableLevel, Ctx->LoggerHandle);
|
|
|
|
break;
|
|
}
|
|
|
|
case WMI_DISABLE_EVENTS:
|
|
{
|
|
Ctx->LoggerHandle = 0;
|
|
Ctx->EnableFlags = 0;
|
|
Ctx->EnableLevel = 0;
|
|
MyDbgPrint(3, "[WMILIB] WMI_DISABLE_EVENTS Ctx 0x%1!08X!\n", Ctx);
|
|
break;
|
|
}
|
|
|
|
default:
|
|
{
|
|
Status = ERROR_INVALID_PARAMETER;
|
|
break;
|
|
}
|
|
}
|
|
*InOutBufferSize = 0;
|
|
return(Status);
|
|
}
|
|
|
|
|
|
|
|
VOID RegisterIfNecessary(
|
|
LPWSTR KeyName,
|
|
LPCGUID Guid)
|
|
{
|
|
WIDE_STRING_MAP::iterator i = map->find(KeyName);
|
|
if ( i == map->end() ) {
|
|
MyDbgPrint(2, "[WMILIB] map: %1!ws!, not found\n", KeyName);
|
|
return; // Not found //
|
|
}
|
|
MyDbgPrint(3, "[WMILIB] map[%1!ws!]=0x%2!08X!\n", i->first, i->second);
|
|
|
|
TRACE_GUID_REGISTRATION Reg;
|
|
|
|
Reg.Guid = Guid;
|
|
Reg.RegHandle = 0;
|
|
|
|
ULONG status = RegisterTraceGuids(
|
|
WmilibControlCallback,
|
|
i->second, // Context for the callback
|
|
Guid, // Control Guid
|
|
1, // # of dummies
|
|
&Reg, // dummy trace guid
|
|
0, //ImagePath,
|
|
0, //ResourceName,
|
|
&i->second->RegistrationHandle
|
|
);
|
|
|
|
if (status == ERROR_SUCCESS) {
|
|
i->second->Next = head;
|
|
head = i->second;
|
|
} else {
|
|
MyDbgPrint(1, "[WMILIB] Failed to register %1!ws!, status %2!d!\n", KeyName, status);
|
|
}
|
|
}
|
|
|
|
ULONG
|
|
WmlInitialize(
|
|
IN LPWSTR ProductName,
|
|
IN WMILIBPRINTFUNC PrintFunc,
|
|
OUT WMILIB_REG_HANDLE* Head,
|
|
... // Pairs: LPWSTR CtrlGuidName, Corresponding WMILIB_REG_STRUCT
|
|
)
|
|
{
|
|
WIDE_STRING_MAP map;
|
|
LPWSTR str;
|
|
va_list ap;
|
|
|
|
WmiLibPrint = PrintFunc;
|
|
|
|
*Head = 0;
|
|
|
|
::head = 0;
|
|
::map = ↦
|
|
|
|
va_start(ap, Head);
|
|
while(0 != (str = va_arg(ap, LPWSTR)) ) {
|
|
map[ str ] = va_arg(ap, PWMILIB_REG_STRUCT);
|
|
}
|
|
va_end(ap);
|
|
ULONG status = InitWmiInternal(0, ProductName, 0);
|
|
*Head = ::head;
|
|
return status;
|
|
}
|
|
|
|
VOID
|
|
WmlUninitialize(
|
|
IN PWMILIB_REG_STRUCT head
|
|
)
|
|
{
|
|
while (head) {
|
|
MyDbgPrint(3,"[WMILIB] Unregister 0x%1!08X!\n", head);
|
|
UnregisterTraceGuids(head->RegistrationHandle);
|
|
head = head->Next;
|
|
}
|
|
}
|
|
|
|
#define WMILIB_USER_MODE
|
|
|
|
typedef struct _TRACE_BUFFER {
|
|
union {
|
|
EVENT_TRACE_HEADER Trace;
|
|
WNODE_HEADER Wnode;
|
|
};
|
|
MOF_FIELD MofFields[MAX_MOF_FIELDS + 1];
|
|
} TRACE_BUFFER, *PTRACE_BUFFER;
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////
|
|
// 0 | Size | ProviderId | 0 |Size.HT.Mk | Typ.Lev.Version|
|
|
// 2 | L o g g e r H a n d l e | 2 | T h r e a d I d |
|
|
// 4 | T i m e S t a m p | 4 | T i m e S t a m p |
|
|
// 6 | G U I D L o w | 6 | GUID Ptr / Guid L o w |
|
|
// 8 | G U I D H I g h | 8 | G U I D H i g h |
|
|
// 10 | ClientCtx | Flags | 10 |KernelTime | UserTime |
|
|
//////////////////////////////////////////////////////////////////////
|
|
|
|
ULONG
|
|
WmlTrace(
|
|
IN UINT Type,
|
|
IN LPCGUID TraceGuid,
|
|
IN TRACEHANDLE LoggerHandle,
|
|
... // Pairs: Address, Length
|
|
)
|
|
{
|
|
TRACE_BUFFER TraceBuffer;
|
|
|
|
((PULONG)&TraceBuffer)[1] = Type;
|
|
|
|
#ifndef WMILIB_USER_MODE
|
|
TraceBuffer.Wnode.HistoricalContext = LoggerHandle;
|
|
#endif
|
|
|
|
TraceBuffer.Trace.Guid = *TraceGuid;
|
|
|
|
TraceBuffer.Wnode.Flags =
|
|
WNODE_FLAG_USE_MOF_PTR | // MOF data are dereferenced
|
|
WNODE_FLAG_TRACED_GUID; // Trace Event, not a WMI event
|
|
|
|
{
|
|
PMOF_FIELD ptr = TraceBuffer.MofFields;
|
|
va_list ap;
|
|
|
|
va_start(ap, LoggerHandle);
|
|
do {
|
|
if ( 0 == (ptr->Length = (ULONG)va_arg (ap, size_t)) ) {
|
|
break;
|
|
}
|
|
ptr->DataPtr = (ULONGLONG)va_arg(ap, PVOID);
|
|
} while ( ++ptr < &TraceBuffer.MofFields[MAX_MOF_FIELDS] );
|
|
va_end(ap);
|
|
|
|
TraceBuffer.Wnode.BufferSize = (ULONG) ((ULONG_PTR)ptr - (ULONG_PTR)&TraceBuffer);
|
|
}
|
|
|
|
#ifdef WMILIB_USER_MODE
|
|
ULONG status = TraceEvent( LoggerHandle, &TraceBuffer.Trace);
|
|
if (status != ERROR_SUCCESS) {
|
|
// Need to count failures and report them during unintialize or ...//
|
|
}
|
|
#else
|
|
IoWMIWriteEvent(&TraceBuffer);
|
|
#endif
|
|
return ERROR_SUCCESS;
|
|
}
|
|
|