3133 lines
93 KiB
C++
3133 lines
93 KiB
C++
// begin_sdk
|
|
/*++
|
|
|
|
Copyright (c) 1997-2000 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
tracedmp.c
|
|
|
|
Abstract:
|
|
|
|
Sample trace consumer program. Converts binary
|
|
Event Trace Log (ETL) to CSV format
|
|
|
|
// end_sdk
|
|
Author:
|
|
|
|
Jee Fung Pang (jeepang) 03-Dec-1997
|
|
|
|
Revision History:
|
|
Corey Morgan (coreym) 24-May-2000 Added MOF version support
|
|
|
|
Insung Park (insungp) 16-Jan-2001
|
|
|
|
tracedmp no longer uses MOF data file. All the layout information
|
|
comes from the WBEM namespace. Also added support for float numbers.
|
|
Also added comments for all the functions.
|
|
|
|
// begin_sdk
|
|
--*/
|
|
|
|
#include <stdlib.h>
|
|
#include <stdio.h>
|
|
#include <windows.h>
|
|
#include <wbemidl.h>
|
|
#include <shellapi.h>
|
|
#include <tchar.h>
|
|
#include <wmistr.h>
|
|
#include <objbase.h>
|
|
#include <initguid.h>
|
|
#include <evntrace.h>
|
|
#include <objidl.h>
|
|
|
|
#define MAXLOGFILES 16
|
|
#define MAXSTR 1024
|
|
#define MOFWSTR 16360
|
|
#define MOFSTR 32720
|
|
#define MAXTYPE 256
|
|
#define UC(x) ( (UINT)((x) & 0xFF) )
|
|
#define NTOHS(x) ( (UC(x) * 256) + UC((x) >> 8) )
|
|
// Maximum number of properties per WBEM class object: may need to be changed
|
|
#define MAXPROPS 256
|
|
|
|
#define DUMP_FILE_NAME _T("DumpFile.csv")
|
|
#define SUMMARY_FILE_NAME _T("Summary.txt")
|
|
|
|
#define DEFAULT_LOGFILE_NAME _T("C:\\Logfile.Etl")
|
|
|
|
#define DEFAULT_NAMESPACE _T("root\\wmi")
|
|
|
|
#define IsEqualGUID(rguid1, rguid2) (!memcmp(rguid1, rguid2, sizeof(GUID)))
|
|
#define CHECK_WBEM_HR( hr ) if( WBEM_NO_ERROR != hr ){ WbemError(hr); goto cleanup; }
|
|
|
|
#define InitializeListHead(ListHead) (\
|
|
(ListHead)->Flink = (ListHead)->Blink = (ListHead))
|
|
|
|
#define InsertTailList(ListHead,Entry) {\
|
|
PLIST_ENTRY _EX_Blink;\
|
|
PLIST_ENTRY _EX_ListHead;\
|
|
_EX_ListHead = (ListHead);\
|
|
_EX_Blink = _EX_ListHead->Blink;\
|
|
(Entry)->Flink = _EX_ListHead;\
|
|
(Entry)->Blink = _EX_Blink;\
|
|
_EX_Blink->Flink = (Entry);\
|
|
_EX_ListHead->Blink = (Entry);\
|
|
}
|
|
|
|
#define RemoveEntryList(Entry) {\
|
|
PLIST_ENTRY _EX_Blink;\
|
|
PLIST_ENTRY _EX_Flink;\
|
|
_EX_Flink = (Entry)->Flink;\
|
|
_EX_Blink = (Entry)->Blink;\
|
|
_EX_Blink->Flink = _EX_Flink;\
|
|
_EX_Flink->Blink = _EX_Blink;\
|
|
}
|
|
|
|
#define GUID_TYPE_EVENTTRACE _T("EventTrace")
|
|
#define GUID_TYPE_HEADER _T("Header")
|
|
#define GUID_TYPE_UNKNOWN _T("Unknown")
|
|
#define GUID_TYPE_DEFAULT _T("Default")
|
|
|
|
#define EVENT_TYPE_DEFAULT (-1)
|
|
#define EVENT_LEVEL_DEFAULT (-1)
|
|
#define EVENT_VERSION_DEFAULT (-1)
|
|
|
|
#define STR_ItemChar _T("ItemChar")
|
|
#define STR_ItemWChar _T("ItemWChar")
|
|
#define STR_ItemUChar _T("ItemUChar")
|
|
#define STR_ItemCharShort _T("ItemCharShort")
|
|
#define STR_ItemShort _T("ItemShort")
|
|
#define STR_ItemUShort _T("ItemUShort")
|
|
#define STR_ItemLong _T("ItemLong")
|
|
#define STR_ItemULong _T("ItemULong")
|
|
#define STR_ItemULongX _T("ItemULongX")
|
|
#define STR_ItemLongLong _T("ItemLongLong")
|
|
#define STR_ItemULongLong _T("ItemULongLong")
|
|
#define STR_ItemFloat _T("ItemFloat");
|
|
#define STR_ItemDouble _T("ItemDouble");
|
|
#define STR_ItemString _T("ItemString")
|
|
#define STR_ItemWString _T("ItemWString")
|
|
// end_sdk
|
|
#define STR_ItemRString _T("ItemRString")
|
|
#define STR_ItemRWString _T("ItemRWString")
|
|
// begin_sdk
|
|
#define STR_ItemPString _T("ItemPString")
|
|
#define STR_ItemPWString _T("ItemPWString")
|
|
#define STR_ItemDSString _T("ItemDSString")
|
|
#define STR_ItemDSWString _T("ItemDSWString")
|
|
#define STR_ItemMLString _T("ItemMLString")
|
|
#define STR_ItemSid _T("ItemSid")
|
|
#define STR_ItemIPAddr _T("ItemIPAddr")
|
|
#define STR_ItemPort _T("ItemPort")
|
|
#define STR_ItemNWString _T("ItemNWString")
|
|
#define STR_ItemPtr _T("ItemPtr")
|
|
#define STR_ItemGuid _T("ItemGuid")
|
|
// end_sdk
|
|
#define STR_ItemVariant _T("ItemVariant")
|
|
// begin_sdk
|
|
#define STR_ItemBool _T("ItemBool")
|
|
// end_sdk
|
|
#define STR_ItemCPUTime _T("ItemCPUTime")
|
|
#define STR_ItemOptArgs _T("ItemOptArgs")
|
|
// begin_sdk
|
|
|
|
// Data types supported in this consumer.
|
|
typedef enum _ITEM_TYPE {
|
|
// end_sdk
|
|
ItemCPUTime,
|
|
ItemOptArgs,
|
|
// begin_sdk
|
|
ItemChar,
|
|
ItemWChar,
|
|
ItemUChar,
|
|
ItemCharShort,
|
|
ItemShort,
|
|
ItemUShort,
|
|
ItemLong,
|
|
ItemULong,
|
|
ItemULongX,
|
|
ItemLongLong,
|
|
ItemULongLong,
|
|
ItemFloat,
|
|
ItemDouble,
|
|
ItemString,
|
|
ItemWString,
|
|
// end_sdk
|
|
ItemRString,
|
|
ItemRWString,
|
|
// begin_sdk
|
|
ItemPString,
|
|
ItemPWString,
|
|
ItemDSString,
|
|
ItemDSWString,
|
|
ItemSid,
|
|
ItemIPAddr,
|
|
ItemPort,
|
|
ItemMLString,
|
|
ItemNWString, // Non-null terminated Wide Char String
|
|
ItemPtr,
|
|
ItemGuid,
|
|
// end_sdk
|
|
ItemVariant,
|
|
// begin_sdk
|
|
ItemBool,
|
|
ItemUnknown
|
|
} ITEM_TYPE;
|
|
|
|
// Construct that represents an event layout
|
|
typedef struct _MOF_INFO {
|
|
LIST_ENTRY Entry;
|
|
LPTSTR strDescription; // Class Name
|
|
ULONG EventCount;
|
|
GUID Guid;
|
|
PLIST_ENTRY ItemHeader;
|
|
LPTSTR strType; // Type Name
|
|
SHORT TypeIndex;
|
|
SHORT Version;
|
|
CHAR Level;
|
|
} MOF_INFO, *PMOF_INFO;
|
|
|
|
typedef struct _ITEM_DESC *PITEM_DESC;
|
|
// Construct that represents one data item
|
|
typedef struct _ITEM_DESC {
|
|
LIST_ENTRY Entry;
|
|
LPTSTR strDescription;
|
|
ULONG DataSize;
|
|
ITEM_TYPE ItemType;
|
|
UINT ArraySize;
|
|
} ITEM_DESC;
|
|
|
|
void
|
|
PrintHelpMessage();
|
|
|
|
PMOF_INFO
|
|
GetNewMofInfo(
|
|
GUID guid,
|
|
SHORT nType,
|
|
SHORT nVersion,
|
|
CHAR nLevel
|
|
);
|
|
|
|
void
|
|
AddMofInfo(
|
|
PLIST_ENTRY List,
|
|
LPTSTR strType,
|
|
ITEM_TYPE nType,
|
|
UINT ArraySize
|
|
);
|
|
|
|
HRESULT
|
|
WbemConnect(
|
|
IWbemServices** pWbemServices
|
|
);
|
|
|
|
ULONG GetArraySize(
|
|
IN IWbemQualifierSet *pQualSet
|
|
);
|
|
|
|
ITEM_TYPE
|
|
GetItemType(
|
|
IN CIMTYPE_ENUMERATION CimType,
|
|
IN IWbemQualifierSet *pQualSet
|
|
);
|
|
|
|
PMOF_INFO
|
|
GetPropertiesFromWBEM(
|
|
IWbemClassObject *pTraceSubClasses,
|
|
GUID Guid,
|
|
SHORT nVersion,
|
|
CHAR nLevel,
|
|
SHORT nType
|
|
);
|
|
|
|
PMOF_INFO
|
|
GetGuids(
|
|
GUID Guid,
|
|
SHORT nVersion,
|
|
CHAR nLevel,
|
|
SHORT nType
|
|
);
|
|
|
|
ULONG
|
|
ahextoi(
|
|
TCHAR *s
|
|
);
|
|
|
|
// end_sdk
|
|
static
|
|
void
|
|
reduceW(
|
|
WCHAR *Src
|
|
);
|
|
|
|
static
|
|
void
|
|
reduceA(
|
|
char *Src
|
|
);
|
|
// begin_sdk
|
|
|
|
PMOF_INFO
|
|
GetMofInfoHead(
|
|
GUID Guid,
|
|
SHORT nType,
|
|
SHORT nVersion,
|
|
CHAR nLevel
|
|
);
|
|
|
|
ULONG
|
|
CheckFile(
|
|
LPTSTR fileName
|
|
);
|
|
|
|
void
|
|
CleanupEventList(
|
|
VOID
|
|
);
|
|
|
|
ULONG
|
|
WINAPI
|
|
BufferCallback(
|
|
PEVENT_TRACE_LOGFILE pLog
|
|
);
|
|
|
|
void
|
|
WINAPI
|
|
DumpEvent(
|
|
PEVENT_TRACE pEvent
|
|
);
|
|
|
|
void
|
|
RemoveMofInfo(
|
|
PLIST_ENTRY pMofInfo
|
|
);
|
|
|
|
void
|
|
GuidToString(
|
|
PTCHAR s,
|
|
LPGUID piid
|
|
);
|
|
|
|
HRESULT
|
|
ParseTime(
|
|
LPTSTR strTime,
|
|
SYSTEMTIME* pstTime
|
|
);
|
|
|
|
// output files
|
|
FILE* DumpFile = NULL;
|
|
FILE* SummaryFile = NULL;
|
|
|
|
static ULONG TotalBuffersRead = 0;
|
|
static ULONG TotalEventsLost = 0;
|
|
static ULONG TotalEventCount = 0;
|
|
static ULONG TimerResolution = 10;
|
|
// end_sdk
|
|
static ULONG SysTimerResolution = 100000;
|
|
// begin_sdk
|
|
static ULONGLONG StartTime = 0;
|
|
static ULONGLONG EndTime = 0;
|
|
static BOOL fNoEndTime = FALSE;
|
|
static __int64 ElapseTime;
|
|
|
|
PCHAR MofData = NULL;
|
|
size_t MofLength = 0;
|
|
BOOLEAN fSummaryOnly = FALSE;
|
|
BOOLEAN fDebugDisplay = FALSE;
|
|
// end_sdk
|
|
BOOLEAN fIgnorePerfClock = FALSE;
|
|
// begin_sdk
|
|
BOOLEAN fRealTimeCircular = FALSE;
|
|
ULONG PointerSize = sizeof(PVOID) * 8;
|
|
|
|
// Global head for event layout linked list
|
|
PLIST_ENTRY EventListHead = NULL;
|
|
|
|
// log files
|
|
PEVENT_TRACE_LOGFILE EvmFile[MAXLOGFILES];
|
|
|
|
ULONG LogFileCount = 0;
|
|
BOOL g_bUserMode = FALSE;
|
|
// end_sdk
|
|
TCHAR ComputerName[MAXSTR];
|
|
DWORD ComputerNameLength = 0;
|
|
// begin_sdk
|
|
// cached Wbem pointer
|
|
IWbemServices *pWbemServices = NULL;
|
|
|
|
int __cdecl main (int argc, LPTSTR* argv)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
It is the main function.
|
|
|
|
Arguments:
|
|
Usage: tracedmp [options] <EtlFile1 EtlFile2 ...>| [-h | -? | -help]
|
|
-o <file> Output CSV file
|
|
-rt [LoggerName] Realtime tracedmp from the logger [LoggerName]
|
|
-summary Summary.txt only
|
|
-begin HH:MM DD/MM/YY
|
|
-end HH:MM DD/MM/YY
|
|
-h
|
|
-help
|
|
-? Display usage information
|
|
|
|
Return Value:
|
|
|
|
Error Code defined in winerror.h : If the function succeeds,
|
|
it returns ERROR_SUCCESS (== 0).
|
|
|
|
--*/
|
|
{
|
|
TCHAR DumpFileName[MAXSTR];
|
|
TCHAR SummaryFileName[MAXSTR];
|
|
|
|
LPTSTR *targv;
|
|
FILETIME ftStart;
|
|
FILETIME ftEnd;
|
|
SYSTEMTIME st;
|
|
|
|
#ifdef UNICODE
|
|
LPTSTR *cmdargv;
|
|
#endif
|
|
|
|
PEVENT_TRACE_LOGFILE pLogFile;
|
|
ULONG Status = ERROR_SUCCESS;
|
|
ULONG i, j;
|
|
TRACEHANDLE HandleArray[MAXLOGFILES];
|
|
|
|
#ifdef UNICODE
|
|
if ((cmdargv = CommandLineToArgvW(
|
|
GetCommandLineW(), // pointer to a command-line string
|
|
&argc // receives the argument count
|
|
)) == NULL)
|
|
{
|
|
return(GetLastError());
|
|
};
|
|
targv = cmdargv ;
|
|
#else
|
|
targv = argv;
|
|
#endif
|
|
|
|
RtlZeroMemory( &ftStart, sizeof(FILETIME) );
|
|
RtlZeroMemory( &ftEnd, sizeof(FILETIME) );
|
|
|
|
_tcscpy(DumpFileName, DUMP_FILE_NAME);
|
|
_tcscpy(SummaryFileName, SUMMARY_FILE_NAME);
|
|
|
|
while (--argc > 0) {
|
|
++targv;
|
|
if (**targv == '-' || **targv == '/') { // argument found
|
|
if( **targv == '/' ){
|
|
**targv = '-';
|
|
}
|
|
if ( !_tcsicmp(targv[0], _T("-begin") )) {
|
|
if (argc > 1) {
|
|
if (targv[1][0] != '-' && targv[1][0] != '/') {
|
|
TCHAR buffer[MAXSTR];
|
|
_tcscpy( buffer, targv[1] );
|
|
_tcscat( buffer, _T(" ") );
|
|
++targv; --argc;
|
|
if (targv[1][0] != '-' && targv[1][0] != '/'){
|
|
_tcscat( buffer, targv[1] );
|
|
ParseTime( buffer, &st );
|
|
SystemTimeToFileTime( &st, &ftStart );
|
|
++targv; --argc;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else if ( !_tcsicmp(targv[0], _T("-end")) ) {
|
|
if (argc > 1) {
|
|
if (targv[1][0] != '-' && targv[1][0] != '/') {
|
|
TCHAR buffer[MAXSTR];
|
|
_tcscpy( buffer, targv[1] );
|
|
_tcscat( buffer, _T(" ") );
|
|
++targv; --argc;
|
|
if (targv[1][0] != '-' && targv[1][0] != '/'){
|
|
_tcscat( buffer, targv[1] );
|
|
ParseTime( buffer, &st );
|
|
SystemTimeToFileTime( &st, &ftEnd );
|
|
++targv; --argc;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else if ( !_tcsicmp(targv[0], _T("-summary")) ) {
|
|
fSummaryOnly = TRUE;
|
|
}
|
|
else if ( !_tcsicmp(targv[0], _T("-debug")) ) {
|
|
fDebugDisplay = TRUE;
|
|
}
|
|
// end_sdk
|
|
else if ( !_tcsicmp(targv[0], _T("-IgnorePerfClock")) ) {
|
|
fIgnorePerfClock = TRUE;
|
|
}
|
|
// begin_sdk
|
|
else if ( !_tcsicmp(targv[0], _T("-RealTimeCircular")) ) {
|
|
fRealTimeCircular = TRUE;
|
|
}
|
|
else if (targv[0][1] == 'h' || targv[0][1] == 'H'
|
|
|| targv[0][1] == '?')
|
|
{
|
|
PrintHelpMessage();
|
|
return 0;
|
|
}
|
|
else if ( !_tcsicmp(targv[0], _T("-rt")) ) {
|
|
TCHAR LoggerName[MAXSTR];
|
|
_tcscpy(LoggerName, KERNEL_LOGGER_NAME);
|
|
if (argc > 1) {
|
|
if (targv[1][0] != '-' && targv[1][0] != '/') {
|
|
++targv; --argc;
|
|
_tcscpy(LoggerName, targv[0]);
|
|
}
|
|
}
|
|
|
|
pLogFile = (PEVENT_TRACE_LOGFILE) malloc(sizeof(EVENT_TRACE_LOGFILE));
|
|
if (pLogFile == NULL){
|
|
_tprintf(_T("Allocation Failure\n"));
|
|
Status = ERROR_OUTOFMEMORY;
|
|
goto cleanup;
|
|
}
|
|
RtlZeroMemory(pLogFile, sizeof(EVENT_TRACE_LOGFILE));
|
|
EvmFile[LogFileCount] = pLogFile;
|
|
|
|
EvmFile[LogFileCount]->LogFileName = NULL;
|
|
EvmFile[LogFileCount]->LoggerName =
|
|
(LPTSTR) malloc(MAXSTR*sizeof(TCHAR));
|
|
|
|
if ( EvmFile[LogFileCount]->LoggerName == NULL ) {
|
|
_tprintf(_T("Allocation Failure\n"));
|
|
Status = ERROR_OUTOFMEMORY;
|
|
goto cleanup;
|
|
}
|
|
_tcscpy(EvmFile[LogFileCount]->LoggerName, LoggerName);
|
|
|
|
_tprintf(_T("Setting RealTime mode for %s\n"),
|
|
EvmFile[LogFileCount]->LoggerName);
|
|
|
|
EvmFile[LogFileCount]->Context = NULL;
|
|
EvmFile[LogFileCount]->BufferCallback = BufferCallback;
|
|
EvmFile[LogFileCount]->BuffersRead = 0;
|
|
EvmFile[LogFileCount]->CurrentTime = 0;
|
|
EvmFile[LogFileCount]->EventCallback = &DumpEvent;
|
|
EvmFile[LogFileCount]->LogFileMode = EVENT_TRACE_REAL_TIME_MODE;
|
|
LogFileCount++;
|
|
}
|
|
else if ( !_tcsicmp(targv[0], _T("-o")) ) {
|
|
if (argc > 1) {
|
|
if (targv[1][0] != '-' && targv[1][0] != '/') {
|
|
TCHAR drive[10];
|
|
TCHAR path[MAXSTR];
|
|
TCHAR file[MAXSTR];
|
|
TCHAR ext[MAXSTR];
|
|
++targv; --argc;
|
|
|
|
_tfullpath(DumpFileName, targv[0], MAXSTR);
|
|
_tsplitpath( DumpFileName, drive, path, file, ext );
|
|
_tcscpy(ext,_T("csv"));
|
|
_tmakepath( DumpFileName, drive, path, file, ext );
|
|
_tcscpy(ext,_T("txt"));
|
|
_tmakepath( SummaryFileName, drive, path, file, ext );
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else {
|
|
pLogFile = (PEVENT_TRACE_LOGFILE) malloc(sizeof(EVENT_TRACE_LOGFILE));
|
|
if (pLogFile == NULL){
|
|
_tprintf(_T("Allocation Failure\n"));
|
|
Status = ERROR_OUTOFMEMORY;
|
|
goto cleanup;
|
|
}
|
|
RtlZeroMemory(pLogFile, sizeof(EVENT_TRACE_LOGFILE));
|
|
EvmFile[LogFileCount] = pLogFile;
|
|
|
|
EvmFile[LogFileCount]->LoggerName = NULL;
|
|
EvmFile[LogFileCount]->LogFileName =
|
|
(LPTSTR) malloc(MAXSTR*sizeof(TCHAR));
|
|
if (EvmFile[LogFileCount]->LogFileName == NULL) {
|
|
_tprintf(_T("Allocation Failure\n"));
|
|
Status = ERROR_OUTOFMEMORY;
|
|
goto cleanup;
|
|
}
|
|
|
|
_tfullpath(EvmFile[LogFileCount]->LogFileName, targv[0], MAXSTR);
|
|
_tprintf(_T("Setting log file to: %s\n"),
|
|
EvmFile[LogFileCount]->LogFileName);
|
|
// If one of the log files is not readable, exit.
|
|
if (!CheckFile(EvmFile[LogFileCount]->LogFileName)) {
|
|
_tprintf(_T("Cannot open logfile for reading\n"));
|
|
Status = ERROR_INVALID_PARAMETER;
|
|
goto cleanup;
|
|
}
|
|
EvmFile[LogFileCount]->Context = NULL;
|
|
EvmFile[LogFileCount]->BufferCallback = BufferCallback;
|
|
EvmFile[LogFileCount]->BuffersRead = 0;
|
|
EvmFile[LogFileCount]->CurrentTime = 0;
|
|
EvmFile[LogFileCount]->EventCallback = &DumpEvent;
|
|
LogFileCount++;
|
|
}
|
|
}
|
|
|
|
if (LogFileCount <= 0) {
|
|
PrintHelpMessage();
|
|
return Status;
|
|
}
|
|
|
|
for (i = 0; i < LogFileCount; i++) {
|
|
TRACEHANDLE x;
|
|
|
|
// end_sdk
|
|
if (fIgnorePerfClock)
|
|
EvmFile[i]->LogfileHeader.ReservedFlags |= 0x00000002;
|
|
// begin_sdk
|
|
if (fRealTimeCircular)
|
|
EvmFile[i]->LogfileHeader.ReservedFlags |= 0x00000004;
|
|
x = OpenTrace(EvmFile[i]);
|
|
HandleArray[i] = x;
|
|
if (HandleArray[i] == 0) {
|
|
Status = GetLastError();
|
|
_tprintf(_T("Error Opening Trace %d with status=%d\n"),
|
|
i, Status);
|
|
|
|
for (j = 0; j < i; j++)
|
|
CloseTrace(HandleArray[j]);
|
|
goto cleanup;
|
|
}
|
|
}
|
|
|
|
if (!fSummaryOnly)
|
|
{
|
|
DumpFile = _tfopen(DumpFileName, _T("w"));
|
|
if (DumpFile == NULL) {
|
|
Status = ERROR_INVALID_PARAMETER;
|
|
_tprintf(_T("DumpFile is NULL\n"));
|
|
goto cleanup;
|
|
}
|
|
}
|
|
SummaryFile = _tfopen(SummaryFileName, _T("w"));
|
|
if (SummaryFile == NULL) {
|
|
Status = ERROR_INVALID_PARAMETER;
|
|
_tprintf(_T("SummaryFile is NULL\n"));
|
|
goto cleanup;
|
|
}
|
|
|
|
if (!fSummaryOnly)
|
|
{
|
|
_ftprintf(DumpFile,
|
|
_T("%12s, %10s,%7s,%21s,%11s,%11s, User Data\n"),
|
|
_T("Event Name"), _T("Type"), _T("TID"), _T("Clock-Time"),
|
|
_T("Kernel(ms)"), _T("User(ms)")
|
|
);
|
|
}
|
|
|
|
Status = ProcessTrace(
|
|
HandleArray,
|
|
LogFileCount,
|
|
&ftStart,
|
|
&ftEnd
|
|
);
|
|
|
|
if (Status != ERROR_SUCCESS) {
|
|
_tprintf(_T("Error processing with status=%dL (GetLastError=0x%x)\n"),
|
|
Status, GetLastError());
|
|
}
|
|
|
|
for (j = 0; j < LogFileCount; j++){
|
|
Status = CloseTrace(HandleArray[j]);
|
|
if (Status != ERROR_SUCCESS) {
|
|
_tprintf(_T("Error Closing Trace %d with status=%d\n"), j, Status);
|
|
}
|
|
}
|
|
|
|
_ftprintf(SummaryFile,_T("Files Processed:\n"));
|
|
for (i=0; i<LogFileCount; i++) {
|
|
_ftprintf(SummaryFile,_T("\t%s\n"),EvmFile[i]->LogFileName);
|
|
}
|
|
|
|
ElapseTime = EndTime - StartTime;
|
|
_ftprintf(SummaryFile,
|
|
_T("Total Buffers Processed %d\n")
|
|
_T("Total Events Processed %d\n")
|
|
_T("Total Events Lost %d\n")
|
|
_T("Start Time 0x%016I64X\n")
|
|
_T("End Time 0x%016I64X\n")
|
|
_T("Elapsed Time %I64d sec\n"),
|
|
TotalBuffersRead,
|
|
TotalEventCount,
|
|
TotalEventsLost,
|
|
StartTime,
|
|
EndTime,
|
|
(ElapseTime / 10000000) );
|
|
|
|
_ftprintf(SummaryFile,
|
|
_T("+-------------------------------------------------------------------------------------+\n")
|
|
_T("|%10s %-20s %-10s %-36s |\n")
|
|
_T("+-------------------------------------------------------------------------------------+\n"),
|
|
_T("EventCount"),
|
|
_T("EventName"),
|
|
_T("EventType"),
|
|
_T("Guid")
|
|
);
|
|
|
|
CleanupEventList();
|
|
|
|
_ftprintf(SummaryFile,
|
|
_T("+-------------------------------------------------------------------------------------+\n")
|
|
);
|
|
|
|
cleanup:
|
|
if (!fSummaryOnly && DumpFile != NULL) {
|
|
_tprintf(_T("Event traces dumped to %s\n"), DumpFileName);
|
|
fclose(DumpFile);
|
|
}
|
|
|
|
if(SummaryFile != NULL){
|
|
_tprintf(_T("Event Summary dumped to %s\n"), SummaryFileName);
|
|
fclose(SummaryFile);
|
|
}
|
|
|
|
for (i = 0; i < LogFileCount; i ++)
|
|
{
|
|
if (EvmFile[i]->LoggerName != NULL)
|
|
{
|
|
free(EvmFile[i]->LoggerName);
|
|
EvmFile[i]->LoggerName = NULL;
|
|
}
|
|
if (EvmFile[i]->LogFileName != NULL)
|
|
{
|
|
free(EvmFile[i]->LogFileName);
|
|
EvmFile[i]->LogFileName = NULL;
|
|
}
|
|
free(EvmFile[i]);
|
|
}
|
|
#ifdef UNICODE
|
|
GlobalFree(cmdargv);
|
|
#endif
|
|
|
|
SetLastError(Status);
|
|
if(Status != ERROR_SUCCESS ){
|
|
_tprintf(_T("Exit Status: %d\n"), Status);
|
|
}
|
|
|
|
if (MofData != NULL)
|
|
free(MofData);
|
|
|
|
return Status;
|
|
}
|
|
|
|
HRESULT
|
|
ParseTime(
|
|
LPTSTR strTime,
|
|
SYSTEMTIME* pstTime
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Parse time given in a string into SYSTEMTIME.
|
|
|
|
Arguments:
|
|
|
|
strTime - String that shows time.
|
|
pstTime - Struct to contain the parsed time information.
|
|
|
|
Return Value:
|
|
|
|
Error Code defined in winerror.h : If the function succeeds,
|
|
it returns ERROR_SUCCESS (== 0).
|
|
|
|
--*/
|
|
{
|
|
TCHAR buffer[MAXSTR];
|
|
LPTSTR str, str2;
|
|
ZeroMemory( pstTime, sizeof( SYSTEMTIME ) );
|
|
|
|
if( pstTime == NULL ){
|
|
return ERROR_BAD_ARGUMENTS;
|
|
}
|
|
|
|
_tcscpy( buffer, strTime );
|
|
str = _tcstok( buffer, _T(" \n\t") );
|
|
str2 = _tcstok( NULL, _T(" \n\t") );
|
|
while( str ){
|
|
if( _tcsstr( str, _T(":") ) ){
|
|
LPTSTR strHour = _tcstok( str, _T(":") );
|
|
LPTSTR strMinute = _tcstok( NULL, _T(":") );
|
|
|
|
if( NULL != strHour ){
|
|
pstTime->wHour = (USHORT)_ttoi( strHour );
|
|
}
|
|
if( NULL != strMinute ){
|
|
pstTime->wMinute = (USHORT)_ttoi( strMinute );
|
|
}
|
|
}
|
|
if( _tcsstr( str, _T("/") ) || _tcsstr( str, _T("\\") ) ){
|
|
LPTSTR strMonth = _tcstok( str, _T("/\\") );
|
|
LPTSTR strDay = _tcstok( NULL, _T("/\\") );
|
|
LPTSTR strYear = _tcstok( NULL, _T("/\\") );
|
|
|
|
if( NULL != strMonth ){
|
|
pstTime->wMonth = (USHORT)_ttoi( strMonth );
|
|
}
|
|
if( NULL != strDay ){
|
|
pstTime->wDay = (USHORT)_ttoi( strDay );
|
|
}
|
|
if( NULL != strYear ){
|
|
pstTime->wYear = (USHORT)_ttoi( strYear );
|
|
}
|
|
}
|
|
str = str2;
|
|
str2 = NULL;
|
|
}
|
|
|
|
return ERROR_SUCCESS;
|
|
}
|
|
|
|
// end_sdk
|
|
static
|
|
void
|
|
reduceA(
|
|
char *Src
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Reduces an ANSI string. Used only for ItemRString.
|
|
|
|
Arguments:
|
|
|
|
Src - String to be reduced.
|
|
|
|
Return Value:
|
|
|
|
None.
|
|
|
|
--*/
|
|
{
|
|
char *Start = Src;
|
|
if (!Src)
|
|
return;
|
|
while (*Src)
|
|
{
|
|
if ('\t' == *Src)
|
|
*Src = ' ';
|
|
else if (',' == *Src)
|
|
*Src = ' ';
|
|
else if ('\n' == *Src)
|
|
*Src = ','; // maybe a bug
|
|
else if ('\r' == *Src)
|
|
*Src = ' ';
|
|
++Src;
|
|
}
|
|
--Src;
|
|
while ((Start < Src) && ((' ' == *Src) || (',' == *Src)))
|
|
{
|
|
*Src = 0x00;
|
|
--Src;
|
|
}
|
|
}
|
|
|
|
static
|
|
void
|
|
reduceW(
|
|
WCHAR *Src
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Reduces a wide string. Used only for ItemRWString.
|
|
|
|
Arguments:
|
|
|
|
Src - Wide string to be reduced.
|
|
|
|
Return Value:
|
|
|
|
None.
|
|
|
|
--*/
|
|
{
|
|
WCHAR *Start = Src;
|
|
if (!Src)
|
|
return;
|
|
while (*Src)
|
|
{
|
|
if (L'\t' == *Src)
|
|
*Src = L' ';
|
|
else if (L',' == *Src)
|
|
*Src = L' ';
|
|
else if (L'\n' == *Src)
|
|
*Src = L',';
|
|
else if (L'\r' == *Src)
|
|
*Src = L' ';
|
|
++Src;
|
|
}
|
|
--Src;
|
|
while ((Start < Src) && ((L' ' == *Src) || (L',' == *Src)))
|
|
{
|
|
*Src = 0x00;
|
|
--Src;
|
|
}
|
|
}
|
|
// begin_sdk
|
|
|
|
ULONG
|
|
WINAPI
|
|
BufferCallback(
|
|
PEVENT_TRACE_LOGFILE pLog
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Callback method for processing a buffer. Does not do anything but
|
|
updating global counters.
|
|
|
|
Arguments:
|
|
|
|
pLog - Pointer to a log file.
|
|
|
|
Return Value:
|
|
|
|
Always TRUE.
|
|
|
|
--*/
|
|
{
|
|
TotalBuffersRead++;
|
|
TotalEventsLost += pLog->EventsLost;
|
|
return (TRUE);
|
|
}
|
|
|
|
void
|
|
WINAPI
|
|
DumpEvent(
|
|
PEVENT_TRACE pEvent
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Callback method for processing an event. It obtains the layout
|
|
information by calling GetMofInfoHead(), which returns the pointer
|
|
to the PMOF_INFO corresponding to the event type. Then it writes
|
|
to the output file.
|
|
|
|
NOTE: Only character arrays are supported in this program.
|
|
|
|
Arguments:
|
|
|
|
pEvent - Pointer to an event.
|
|
|
|
Return Value:
|
|
|
|
None.
|
|
|
|
--*/
|
|
{
|
|
PEVENT_TRACE_HEADER pHeader;
|
|
ULONG i;
|
|
PITEM_DESC pItem;
|
|
char str[MOFSTR];
|
|
WCHAR wstr[MOFWSTR];
|
|
PCHAR ptr;
|
|
ULONG ulongword;
|
|
LONG longword;
|
|
USHORT ushortword;
|
|
SHORT shortword;
|
|
PMOF_INFO pMofInfo;
|
|
PLIST_ENTRY Head, Next;
|
|
char iChar;
|
|
WCHAR iwChar;
|
|
ULONG MofDataUsed;
|
|
|
|
TotalEventCount++;
|
|
|
|
if (pEvent == NULL) {
|
|
_tprintf(_T("Warning: Null Event\n"));
|
|
return;
|
|
}
|
|
|
|
pHeader = (PEVENT_TRACE_HEADER) &pEvent->Header;
|
|
|
|
if( IsEqualGUID(&(pEvent->Header.Guid), &EventTraceGuid) &&
|
|
pEvent->Header.Class.Type == EVENT_TRACE_TYPE_INFO ) {
|
|
|
|
PTRACE_LOGFILE_HEADER head = (PTRACE_LOGFILE_HEADER)pEvent->MofData;
|
|
if( NULL != head ){
|
|
g_bUserMode = (head->LogFileMode & EVENT_TRACE_PRIVATE_LOGGER_MODE);
|
|
|
|
if(head->TimerResolution > 0){
|
|
// end_sdk
|
|
SysTimerResolution = head->TimerResolution;
|
|
// begin_sdk
|
|
TimerResolution = head->TimerResolution / 10000;
|
|
}
|
|
|
|
StartTime = head->StartTime.QuadPart;
|
|
EndTime = head->EndTime.QuadPart;
|
|
fNoEndTime = (EndTime == 0);
|
|
|
|
PointerSize = head->PointerSize * 8;
|
|
// Set pointer size
|
|
if (PointerSize < 16){ // minimum is 16 bits
|
|
PointerSize = 32; // default is 32 bits
|
|
}
|
|
}
|
|
}
|
|
|
|
if (fNoEndTime && EndTime < (ULONGLONG) pHeader->TimeStamp.QuadPart) {
|
|
EndTime = pHeader->TimeStamp.QuadPart;
|
|
}
|
|
|
|
if (MofData == NULL) {
|
|
MofLength = pEvent->MofLength + sizeof(UNICODE_NULL);
|
|
MofData = (PCHAR) malloc(MofLength);
|
|
}
|
|
else if ((pEvent->MofLength + sizeof(UNICODE_NULL)) > MofLength) {
|
|
MofLength = pEvent->MofLength + sizeof(UNICODE_NULL);
|
|
MofData = (PCHAR) realloc(MofData, MofLength);
|
|
}
|
|
|
|
if (MofData == NULL) {
|
|
_tprintf(_T("Allocation Failure\n"));
|
|
return;
|
|
}
|
|
|
|
if (NULL == pEvent->MofData && pEvent->MofLength != 0) {
|
|
_tprintf(_T("Incorrect MOF size\n"));
|
|
return;
|
|
}
|
|
|
|
if (NULL != (pEvent->MofData)) {
|
|
memcpy(MofData, pEvent->MofData, pEvent->MofLength);
|
|
}
|
|
|
|
MofData[pEvent->MofLength] = 0;
|
|
MofData[pEvent->MofLength+1] = 0;
|
|
ptr = MofData;
|
|
MofDataUsed = 0;
|
|
// Find the MOF information for this event
|
|
pMofInfo = GetMofInfoHead (
|
|
pEvent->Header.Guid,
|
|
pEvent->Header.Class.Type,
|
|
pEvent->Header.Class.Version,
|
|
pEvent->Header.Class.Level
|
|
);
|
|
|
|
if( NULL == pMofInfo ){
|
|
return;
|
|
}
|
|
|
|
pMofInfo->EventCount++;
|
|
|
|
if( fSummaryOnly == TRUE ){
|
|
return;
|
|
}
|
|
|
|
if( pMofInfo->strDescription != NULL ){
|
|
_ftprintf( DumpFile, _T("%12s, "), pMofInfo->strDescription );
|
|
}else{
|
|
TCHAR strGuid[MAXSTR];
|
|
GuidToString( strGuid, &pMofInfo->Guid );
|
|
_ftprintf( DumpFile, _T("%12s, "), strGuid );
|
|
}
|
|
|
|
if(pMofInfo->strType != NULL && wcslen(pMofInfo->strType) ){
|
|
_ftprintf( DumpFile, _T("%10s, "), pMofInfo->strType );
|
|
}else{
|
|
_ftprintf( DumpFile, _T("%10d, "), pEvent->Header.Class.Type );
|
|
}
|
|
|
|
// Thread ID
|
|
_ftprintf( DumpFile, _T("0x%04X, "), pHeader->ThreadId );
|
|
|
|
// System Time
|
|
_ftprintf( DumpFile, _T("%20I64u, "), pHeader->TimeStamp.QuadPart);
|
|
|
|
if( g_bUserMode == FALSE ){
|
|
// Kernel Time
|
|
_ftprintf(DumpFile, _T("%10lu, "), pHeader->KernelTime * TimerResolution);
|
|
|
|
// User Time
|
|
_ftprintf(DumpFile, _T("%10lu, "), pHeader->UserTime * TimerResolution);
|
|
}else{
|
|
// processor Time
|
|
_ftprintf(DumpFile, _T("%I64u, "), pHeader->ProcessorTime);
|
|
}
|
|
|
|
Head = pMofInfo->ItemHeader;
|
|
Next = Head->Flink;
|
|
|
|
if ((Head == Next) && (pEvent->MofLength > 0)) {
|
|
_ftprintf(DumpFile, _T("DataSize=%d, "), pEvent->MofLength);
|
|
}
|
|
|
|
while (Head != Next) {
|
|
pItem = CONTAINING_RECORD(Next, ITEM_DESC, Entry);
|
|
Next = Next->Flink;
|
|
|
|
MofDataUsed = (ULONG) (ptr - MofData);
|
|
|
|
if (MofDataUsed >= pEvent->MofLength){
|
|
break;
|
|
}
|
|
|
|
switch (pItem->ItemType)
|
|
{
|
|
case ItemChar:
|
|
case ItemUChar:
|
|
for( i=0;i<pItem->ArraySize;i++){
|
|
iChar = *((PCHAR) ptr);
|
|
_ftprintf(DumpFile, _T("%c"), iChar);
|
|
ptr += sizeof(CHAR);
|
|
}
|
|
_ftprintf(DumpFile, _T(", "));
|
|
break;
|
|
|
|
case ItemWChar:
|
|
for(i=0;i<pItem->ArraySize;i++){
|
|
iwChar = *((PWCHAR) ptr);
|
|
_ftprintf(DumpFile, _T(",%wc"), iwChar);
|
|
ptr += sizeof(WCHAR);
|
|
}
|
|
_ftprintf(DumpFile, _T(", "));
|
|
break;
|
|
|
|
case ItemCharShort:
|
|
iChar = *((PCHAR) ptr);
|
|
_ftprintf(DumpFile, _T("%d, "), iChar);
|
|
ptr += sizeof(CHAR);
|
|
break;
|
|
|
|
case ItemShort:
|
|
shortword = * ((PSHORT) ptr);
|
|
_ftprintf(DumpFile, _T("%6d, "), shortword);
|
|
ptr += sizeof (SHORT);
|
|
break;
|
|
|
|
case ItemUShort:
|
|
ushortword = *((PUSHORT) ptr);
|
|
_ftprintf(DumpFile, _T("%6u, "), ushortword);
|
|
ptr += sizeof (USHORT);
|
|
break;
|
|
|
|
case ItemLong:
|
|
longword = *((PLONG) ptr);
|
|
_ftprintf(DumpFile, _T("%8d, "), longword);
|
|
ptr += sizeof (LONG);
|
|
break;
|
|
|
|
case ItemULong:
|
|
ulongword = *((PULONG) ptr);
|
|
_ftprintf(DumpFile, _T("%8lu, "), ulongword);
|
|
ptr += sizeof (ULONG);
|
|
break;
|
|
|
|
case ItemULongX:
|
|
ulongword = *((PULONG) ptr);
|
|
_ftprintf(DumpFile, _T("0x%08X, "), ulongword);
|
|
ptr += sizeof (ULONG);
|
|
break;
|
|
|
|
case ItemLongLong:
|
|
{
|
|
LONGLONG n64;
|
|
n64 = *((LONGLONG*) ptr);
|
|
ptr += sizeof(LONGLONG);
|
|
_ftprintf(DumpFile, _T("%16I64d, "), n64);
|
|
break;
|
|
}
|
|
|
|
case ItemULongLong:
|
|
{
|
|
ULONGLONG n64;
|
|
n64 = *((ULONGLONG*) ptr);
|
|
ptr += sizeof(ULONGLONG);
|
|
_ftprintf(DumpFile, _T("%16I64u, "), n64);
|
|
break;
|
|
}
|
|
|
|
case ItemFloat:
|
|
{
|
|
float f32;
|
|
f32 = *((float*) ptr);
|
|
ptr += sizeof(float);
|
|
_ftprintf(DumpFile, _T("%f, "), f32);
|
|
break;
|
|
}
|
|
|
|
case ItemDouble:
|
|
{
|
|
double f64;
|
|
f64 = *((double*) ptr);
|
|
ptr += sizeof(double);
|
|
_ftprintf(DumpFile, _T("%f, "), f64);
|
|
break;
|
|
}
|
|
|
|
case ItemPtr :
|
|
{
|
|
unsigned __int64 pointer;
|
|
if (PointerSize == 64) {
|
|
pointer = *((unsigned __int64 *) ptr);
|
|
_ftprintf(DumpFile, _T("0x%X, "), pointer);
|
|
}
|
|
else { // assumes 32 bit otherwise
|
|
ulongword = *((PULONG) ptr);
|
|
_ftprintf(DumpFile, _T("0x%08X, "), ulongword);
|
|
}
|
|
ptr += PointerSize / 8;
|
|
//
|
|
// If target source is Win64, then use Ptr, else use ulongword
|
|
//
|
|
break;
|
|
}
|
|
|
|
case ItemIPAddr:
|
|
{
|
|
ulongword = *((PULONG) ptr);
|
|
|
|
// Convert it to readable form
|
|
_ftprintf(DumpFile, _T("%03d.%03d.%03d.%03d, "),
|
|
(ulongword >> 0) & 0xff,
|
|
(ulongword >> 8) & 0xff,
|
|
(ulongword >> 16) & 0xff,
|
|
(ulongword >> 24) & 0xff);
|
|
ptr += sizeof (ULONG);
|
|
break;
|
|
}
|
|
|
|
case ItemPort:
|
|
{
|
|
_ftprintf(DumpFile, _T("%u, "), NTOHS((USHORT) *ptr));
|
|
ptr += sizeof (USHORT);
|
|
break;
|
|
}
|
|
|
|
case ItemString:
|
|
// end_sdk
|
|
case ItemRString:
|
|
// begin_sdk
|
|
{
|
|
USHORT pLen = (USHORT)strlen((CHAR*) ptr);
|
|
|
|
if (pLen > 0)
|
|
{
|
|
strcpy(str, ptr);
|
|
// end_sdk
|
|
if (pItem->ItemType == ItemRString)
|
|
{
|
|
reduceA(str);
|
|
}
|
|
// begin_sdk
|
|
for (i=pLen-1; i>0; i--) {
|
|
if (str[i] == 0xFF)
|
|
str[i] = 0;
|
|
else break;
|
|
}
|
|
#ifdef UNICODE
|
|
MultiByteToWideChar(CP_ACP, 0, str, -1, wstr, MOFWSTR);
|
|
_ftprintf(DumpFile, _T("\"%ws\","), wstr);
|
|
#else
|
|
_ftprintf(DumpFile, _T("\"%s\","), str);
|
|
#endif
|
|
}
|
|
ptr += (pLen + 1);
|
|
break;
|
|
}
|
|
|
|
case ItemWString:
|
|
// end_sdk
|
|
case ItemRWString:
|
|
// begin_sdk
|
|
{
|
|
size_t pLen = 0;
|
|
size_t i;
|
|
|
|
if (*(WCHAR *) ptr)
|
|
{
|
|
// end_sdk
|
|
if (pItem->ItemType == ItemRWString)
|
|
{
|
|
reduceW((WCHAR *) ptr);
|
|
}
|
|
// begin_sdk
|
|
pLen = ((wcslen((WCHAR*)ptr) + 1) * sizeof(WCHAR));
|
|
memcpy(wstr, ptr, pLen);
|
|
for (i = (pLen/2)-1; i > 0; i--)
|
|
{
|
|
if (((USHORT) wstr[i] == (USHORT) 0xFFFF))
|
|
{
|
|
wstr[i] = (USHORT) 0;
|
|
}
|
|
else break;
|
|
}
|
|
|
|
wstr[pLen / 2] = wstr[(pLen / 2) + 1]= '\0';
|
|
_ftprintf(DumpFile, _T("\"%ws\","), wstr);
|
|
}
|
|
ptr += pLen;
|
|
|
|
break;
|
|
}
|
|
|
|
case ItemDSString: // Counted String
|
|
{
|
|
USHORT pLen = (USHORT)(256 * ((USHORT) * ptr) + ((USHORT) * (ptr + 1)));
|
|
ptr += sizeof(USHORT);
|
|
if (pLen > (pEvent->MofLength - MofDataUsed - 1)) {
|
|
pLen = (USHORT) (pEvent->MofLength - MofDataUsed - 1);
|
|
}
|
|
if (pLen > 0)
|
|
{
|
|
strcpy(str, ptr);
|
|
#ifdef UNICODE
|
|
MultiByteToWideChar(CP_ACP, 0, str, -1, wstr, MOFWSTR);
|
|
fwprintf(DumpFile, _T("\"%ws\","), wstr);
|
|
#else
|
|
fprintf(DumpFile, _T("\"%s\","), str);
|
|
#endif
|
|
}
|
|
ptr += (pLen + 1);
|
|
break;
|
|
}
|
|
|
|
case ItemPString: // Counted String
|
|
{
|
|
USHORT pLen = * ((USHORT *) ptr);
|
|
ptr += sizeof(USHORT);
|
|
|
|
if (pLen > (pEvent->MofLength - MofDataUsed)) {
|
|
pLen = (USHORT) (pEvent->MofLength - MofDataUsed);
|
|
}
|
|
|
|
if (pLen > MOFSTR * sizeof(CHAR)) {
|
|
pLen = MOFSTR * sizeof(CHAR);
|
|
}
|
|
if (pLen > 0) {
|
|
memcpy(str, ptr, pLen);
|
|
str[pLen] = '\0';
|
|
#ifdef UNICODE
|
|
MultiByteToWideChar(CP_ACP, 0, str, -1, wstr, MOFWSTR);
|
|
_ftprintf(DumpFile, _T("\"%ws\","), wstr);
|
|
#else
|
|
_ftprintf(DumpFile, _T("\"%s\","), str);
|
|
#endif
|
|
}
|
|
ptr += pLen;
|
|
break;
|
|
}
|
|
|
|
case ItemDSWString: // DS Counted Wide Strings
|
|
case ItemPWString: // Counted Wide Strings
|
|
{
|
|
USHORT pLen = (USHORT)(( pItem->ItemType == ItemDSWString)
|
|
? (256 * ((USHORT) * ptr) + ((USHORT) * (ptr + 1)))
|
|
: (* ((USHORT *) ptr)));
|
|
|
|
ptr += sizeof(USHORT);
|
|
if (pLen > (pEvent->MofLength - MofDataUsed)) {
|
|
pLen = (USHORT) (pEvent->MofLength - MofDataUsed);
|
|
}
|
|
|
|
if (pLen > MOFWSTR * sizeof(WCHAR)) {
|
|
pLen = MOFWSTR * sizeof(WCHAR);
|
|
}
|
|
if (pLen > 0) {
|
|
memcpy(wstr, ptr, pLen);
|
|
wstr[pLen / sizeof(WCHAR)] = L'\0';
|
|
_ftprintf(DumpFile, _T("\"%ws\","), wstr);
|
|
}
|
|
ptr += pLen;
|
|
break;
|
|
}
|
|
|
|
case ItemNWString: // Non Null Terminated String
|
|
{
|
|
USHORT Size;
|
|
|
|
Size = (USHORT)(pEvent->MofLength - (ULONG)(ptr - MofData));
|
|
if( Size > MOFSTR )
|
|
{
|
|
Size = MOFSTR;
|
|
}
|
|
if (Size > 0)
|
|
{
|
|
memcpy(wstr, ptr, Size);
|
|
wstr[Size / 2] = '\0';
|
|
_ftprintf(DumpFile, _T("\"%ws\","), wstr);
|
|
}
|
|
ptr += Size;
|
|
break;
|
|
}
|
|
|
|
case ItemMLString: // Multi Line String
|
|
{
|
|
USHORT pLen;
|
|
char * src, * dest;
|
|
BOOL inQ = FALSE;
|
|
BOOL skip = FALSE;
|
|
UINT lineCount = 0;
|
|
|
|
ptr += sizeof(UCHAR) * 2;
|
|
pLen = (USHORT)strlen(ptr);
|
|
if (pLen > 0)
|
|
{
|
|
src = ptr;
|
|
dest = str;
|
|
while (* src != '\0'){
|
|
if (* src == '\n'){
|
|
if (!lineCount){
|
|
* dest++ = ' ';
|
|
}
|
|
lineCount++;
|
|
}else if (* src == '\"'){
|
|
if (inQ){
|
|
char strCount[32];
|
|
char * cpy;
|
|
|
|
sprintf(strCount, "{%dx}", lineCount);
|
|
cpy = & strCount[0];
|
|
while (* cpy != '\0'){
|
|
* dest ++ = * cpy ++;
|
|
}
|
|
}
|
|
inQ = !inQ;
|
|
}else if (!skip){
|
|
*dest++ = *src;
|
|
}
|
|
skip = (lineCount > 1 && inQ);
|
|
src++;
|
|
}
|
|
*dest = '\0';
|
|
#ifdef UNICODE
|
|
MultiByteToWideChar(CP_ACP, 0, str, -1, wstr, MOFWSTR);
|
|
_ftprintf(DumpFile, _T("\"%ws\","), wstr);
|
|
#else
|
|
_ftprintf(DumpFile, _T("\"%s\","), str);
|
|
#endif
|
|
}
|
|
ptr += (pLen);
|
|
break;
|
|
}
|
|
|
|
case ItemSid:
|
|
{
|
|
TCHAR UserName[64];
|
|
TCHAR Domain[64];
|
|
TCHAR FullName[256];
|
|
ULONG asize = 0;
|
|
ULONG bsize = 0;
|
|
ULONG Sid[64];
|
|
PULONG pSid = & Sid[0];
|
|
SID_NAME_USE Se;
|
|
ULONG nSidLength;
|
|
|
|
pSid = (PULONG) ptr;
|
|
if (*pSid == 0){
|
|
ptr += 4;
|
|
_ftprintf(DumpFile, _T("%4d, "), *pSid);
|
|
}
|
|
else
|
|
{
|
|
ptr += 8; // skip the TOKEN_USER structure
|
|
nSidLength = 8 + (4*ptr[1]);
|
|
|
|
asize = 64;
|
|
bsize = 64;
|
|
if (LookupAccountSidW(
|
|
NULL,
|
|
(PSID) ptr,
|
|
(LPTSTR) & UserName[0],
|
|
& asize,
|
|
(LPTSTR) & Domain[0],
|
|
& bsize,
|
|
& Se))
|
|
{
|
|
LPTSTR pFullName = &FullName[0];
|
|
_stprintf( pFullName,_T("\\\\%s\\%s"), Domain, UserName);
|
|
asize = (ULONG) _tcslen(pFullName);
|
|
if (asize > 0){
|
|
_ftprintf(DumpFile, _T("\"%s\", "), pFullName);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
_ftprintf(DumpFile, _T("\"System\", "));
|
|
}
|
|
SetLastError( ERROR_SUCCESS );
|
|
ptr += nSidLength;
|
|
}
|
|
break;
|
|
}
|
|
|
|
case ItemGuid:
|
|
{
|
|
TCHAR s[64];
|
|
GuidToString(s, (LPGUID)ptr);
|
|
_ftprintf(DumpFile, _T("%s, "), s);
|
|
ptr += sizeof(GUID);
|
|
break;
|
|
}
|
|
// end_sdk
|
|
case ItemVariant:
|
|
{
|
|
//
|
|
// Variable Size. First ULONG gives the sizee and the rest is blob
|
|
//
|
|
ulongword = *((PULONG) ptr);
|
|
ptr += sizeof(ULONG);
|
|
|
|
_ftprintf(DumpFile, _T("DataSize=%d, "), ulongword);
|
|
|
|
// No need to dump the contents of the Blob itself.
|
|
|
|
ptr += ulongword;
|
|
|
|
break;
|
|
}
|
|
// begin_sdk
|
|
case ItemBool:
|
|
{
|
|
BOOL Flag = (BOOL)*ptr;
|
|
_ftprintf(DumpFile, _T("%5s, "), (Flag) ? _T("TRUE") : _T("FALSE"));
|
|
ptr += sizeof(BOOL);
|
|
break;
|
|
}
|
|
|
|
default:
|
|
ptr += sizeof (int);
|
|
}
|
|
}
|
|
|
|
//Instance ID
|
|
_ftprintf(DumpFile, _T("%d,"), pEvent->InstanceId);
|
|
|
|
//Parent Instance ID
|
|
_ftprintf(DumpFile, _T("%d\n"), pEvent->ParentInstanceId);
|
|
}
|
|
|
|
ULONG
|
|
CheckFile(
|
|
LPTSTR fileName
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Checks whether a file exists and is readable.
|
|
|
|
Arguments:
|
|
|
|
fileName - File name.
|
|
|
|
Return Value:
|
|
|
|
Non-zero if the file exists and is readable. Zero otherwise.
|
|
|
|
--*/
|
|
{
|
|
HANDLE hFile;
|
|
ULONG Status;
|
|
|
|
hFile = CreateFile(
|
|
fileName,
|
|
GENERIC_READ,
|
|
FILE_SHARE_READ | FILE_SHARE_WRITE,
|
|
NULL,
|
|
OPEN_EXISTING,
|
|
FILE_ATTRIBUTE_NORMAL,
|
|
NULL
|
|
);
|
|
Status = (hFile != INVALID_HANDLE_VALUE);
|
|
CloseHandle(hFile);
|
|
return Status;
|
|
}
|
|
|
|
PMOF_INFO
|
|
GetMofInfoHead(
|
|
GUID Guid,
|
|
SHORT nType,
|
|
SHORT nVersion,
|
|
CHAR nLevel
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Find a matching event layout in the global linked list. If it
|
|
is not found in the list, it calls GetGuids() to examine the WBEM
|
|
namespace.
|
|
If the global list is empty, it first creates a header.
|
|
|
|
Arguments:
|
|
|
|
Guid - GUID for the event under consideration.
|
|
nType - Event Type
|
|
nVersion - Event Version
|
|
nLevel - Event Level (not supported in this program)
|
|
|
|
Return Value:
|
|
|
|
Pointer to MOF_INFO for the current event. If the layout
|
|
information is not found anywhere, GetMofInfoHead() creates
|
|
a dummy and returns it.
|
|
|
|
--*/
|
|
{
|
|
PLIST_ENTRY Head, Next;
|
|
PMOF_INFO pMofInfo;
|
|
PMOF_INFO pBestMatch = NULL;
|
|
SHORT nMatchLevel = 0;
|
|
SHORT nMatchCheck;
|
|
|
|
// Search the eventList for this Guid and find the head
|
|
|
|
if (EventListHead == NULL) {
|
|
// Initialize the MOF List and add the global header guid to it
|
|
EventListHead = (PLIST_ENTRY) malloc(sizeof(LIST_ENTRY));
|
|
if (EventListHead == NULL)
|
|
return NULL;
|
|
InitializeListHead(EventListHead);
|
|
|
|
pMofInfo = GetNewMofInfo( EventTraceGuid, EVENT_TYPE_DEFAULT, 0, 0 );
|
|
if( pMofInfo != NULL ){
|
|
InsertTailList( EventListHead, &pMofInfo->Entry );
|
|
pMofInfo->strDescription = (LPTSTR)malloc((_tcslen(GUID_TYPE_EVENTTRACE)+1)*sizeof(TCHAR));
|
|
if( pMofInfo->strDescription != NULL ){
|
|
_tcscpy( pMofInfo->strDescription, GUID_TYPE_EVENTTRACE );
|
|
}
|
|
pMofInfo->strType = (LPTSTR)malloc((_tcslen(GUID_TYPE_HEADER)+1)*sizeof(TCHAR));
|
|
if( pMofInfo->strType != NULL ){
|
|
_tcscpy( pMofInfo->strType, GUID_TYPE_HEADER );
|
|
}
|
|
}
|
|
}
|
|
|
|
// Traverse the list and look for the Mof info head for this Guid.
|
|
|
|
Head = EventListHead;
|
|
Next = Head->Flink;
|
|
|
|
while (Head != Next) {
|
|
|
|
nMatchCheck = 0;
|
|
|
|
pMofInfo = CONTAINING_RECORD(Next, MOF_INFO, Entry);
|
|
Next = Next->Flink;
|
|
|
|
if( IsEqualGUID(&pMofInfo->Guid, &Guid) ){
|
|
|
|
if( pMofInfo->TypeIndex == nType ){
|
|
nMatchCheck++;
|
|
}
|
|
if( pMofInfo->Version == nVersion ){
|
|
nMatchCheck++;
|
|
}
|
|
if( nMatchCheck == 2 ){ // Exact Match
|
|
return pMofInfo;
|
|
}
|
|
|
|
if( nMatchCheck > nMatchLevel ){ // Close Match
|
|
nMatchLevel = nMatchCheck;
|
|
pBestMatch = pMofInfo;
|
|
}
|
|
|
|
if( pMofInfo->TypeIndex == EVENT_TYPE_DEFAULT && // Total Guess
|
|
pBestMatch == NULL ){
|
|
pBestMatch = pMofInfo;
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
if(pBestMatch != NULL){
|
|
return pBestMatch;
|
|
}
|
|
|
|
// If one does not exist in the list, look it up in the file.
|
|
pMofInfo = GetGuids( Guid, nVersion, nLevel, nType );
|
|
|
|
// If still not found, create a unknown place holder
|
|
if( NULL == pMofInfo ){
|
|
pMofInfo = GetNewMofInfo( Guid, nType, nVersion, nLevel );
|
|
if( pMofInfo != NULL ){
|
|
pMofInfo->strDescription = (LPTSTR)malloc((_tcslen(GUID_TYPE_UNKNOWN)+1)*sizeof(TCHAR));
|
|
if( pMofInfo->strDescription != NULL ){
|
|
_tcscpy( pMofInfo->strDescription, GUID_TYPE_UNKNOWN );
|
|
}
|
|
InsertTailList( EventListHead, &pMofInfo->Entry );
|
|
}
|
|
}
|
|
|
|
return pMofInfo;
|
|
}
|
|
|
|
void
|
|
RemoveMofInfo(
|
|
PLIST_ENTRY pMofInfo
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Removes and frees data item structs from a given list.
|
|
|
|
Arguments:
|
|
|
|
pMofInfo - Pointer to the MOF_INFO to be purged of data item structs.
|
|
|
|
Return Value:
|
|
|
|
None.
|
|
|
|
--*/
|
|
{
|
|
PLIST_ENTRY Head, Next;
|
|
PITEM_DESC pItem;
|
|
|
|
Head = pMofInfo;
|
|
Next = Head->Flink;
|
|
while (Head != Next) {
|
|
pItem = CONTAINING_RECORD(Next, ITEM_DESC, Entry);
|
|
Next = Next->Flink;
|
|
RemoveEntryList(&pItem->Entry);
|
|
free(pItem);
|
|
}
|
|
}
|
|
|
|
void
|
|
CleanupEventList(
|
|
VOID
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Cleans up a global event list.
|
|
|
|
Arguments:
|
|
|
|
Return Value:
|
|
|
|
None.
|
|
|
|
--*/
|
|
{
|
|
PLIST_ENTRY Head, Next;
|
|
PMOF_INFO pMofInfo;
|
|
TCHAR s[256];
|
|
TCHAR wstr[256];
|
|
PTCHAR str;
|
|
|
|
if (EventListHead == NULL) {
|
|
return;
|
|
}
|
|
|
|
Head = EventListHead;
|
|
Next = Head->Flink;
|
|
while (Head != Next) {
|
|
RtlZeroMemory(&wstr, 256);
|
|
|
|
pMofInfo = CONTAINING_RECORD(Next, MOF_INFO, Entry);
|
|
|
|
if (pMofInfo->EventCount > 0) {
|
|
GuidToString(&s[0], &pMofInfo->Guid);
|
|
str = s;
|
|
if( pMofInfo->strDescription != NULL ){
|
|
_tcscpy( wstr, pMofInfo->strDescription );
|
|
}
|
|
|
|
_ftprintf(SummaryFile,_T("|%10d %-20s %-10s %36s|\n"),
|
|
pMofInfo->EventCount,
|
|
wstr,
|
|
pMofInfo->strType ? pMofInfo->strType : GUID_TYPE_DEFAULT,
|
|
str);
|
|
}
|
|
|
|
RemoveEntryList(&pMofInfo->Entry);
|
|
RemoveMofInfo(pMofInfo->ItemHeader);
|
|
free(pMofInfo->ItemHeader);
|
|
|
|
if (pMofInfo->strDescription != NULL)
|
|
free(pMofInfo->strDescription);
|
|
if (pMofInfo->strType != NULL)
|
|
free(pMofInfo->strType);
|
|
|
|
Next = Next->Flink;
|
|
free(pMofInfo);
|
|
}
|
|
|
|
free(EventListHead);
|
|
}
|
|
|
|
void
|
|
GuidToString(
|
|
PTCHAR s,
|
|
LPGUID piid
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Converts a GUID into a string.
|
|
|
|
Arguments:
|
|
|
|
s - String that will have the converted GUID.
|
|
piid - GUID
|
|
|
|
Return Value:
|
|
|
|
None.
|
|
|
|
--*/
|
|
{
|
|
_stprintf(s, _T("{%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}"),
|
|
piid->Data1, piid->Data2,
|
|
piid->Data3,
|
|
piid->Data4[0], piid->Data4[1],
|
|
piid->Data4[2], piid->Data4[3],
|
|
piid->Data4[4], piid->Data4[5],
|
|
piid->Data4[6], piid->Data4[7]);
|
|
return;
|
|
}
|
|
|
|
void
|
|
AddMofInfo(
|
|
PLIST_ENTRY List,
|
|
LPTSTR strType,
|
|
ITEM_TYPE nType,
|
|
UINT ArraySize
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Creates a data item information struct (ITEM_DESC) and appends
|
|
it to all MOF_INFOs in the given list.
|
|
GetPropertiesFromWBEM() creates a list of MOF_INFOs for multiple
|
|
types, stores them in a temporary list and calls this function for
|
|
each data item information it encounters.
|
|
|
|
Arguments:
|
|
|
|
List - List of MOF_INFOs.
|
|
strType - Item description in string.
|
|
nType - ITEM_TYPE defined at the beginning of this file.
|
|
ArraySize - Size of array of this type of items, if applicable.
|
|
|
|
Return Value:
|
|
|
|
None.
|
|
|
|
--*/
|
|
{
|
|
PITEM_DESC pItem;
|
|
PMOF_INFO pMofInfo;
|
|
|
|
PLIST_ENTRY Head = List;
|
|
PLIST_ENTRY Next = Head->Flink;
|
|
while (Head != Next) {
|
|
|
|
pMofInfo = CONTAINING_RECORD(Next, MOF_INFO, Entry);
|
|
Next = Next->Flink;
|
|
|
|
if( NULL != pMofInfo ){
|
|
|
|
pItem = (PITEM_DESC) malloc(sizeof(ITEM_DESC));
|
|
if( NULL == pItem ){
|
|
return;
|
|
}
|
|
ZeroMemory( pItem, sizeof(ITEM_DESC) );
|
|
pItem->ItemType = nType;
|
|
pItem->ArraySize = ArraySize;
|
|
|
|
pItem->strDescription = (LPTSTR) malloc( (_tcslen(strType)+1)*sizeof(TCHAR));
|
|
|
|
if( NULL == pItem->strDescription ){
|
|
free( pItem );
|
|
return;
|
|
}
|
|
_tcscpy(pItem->strDescription, strType);
|
|
|
|
InsertTailList( (pMofInfo->ItemHeader), &pItem->Entry);
|
|
}
|
|
|
|
}
|
|
}
|
|
|
|
|
|
PMOF_INFO
|
|
GetNewMofInfo(
|
|
GUID guid,
|
|
SHORT nType,
|
|
SHORT nVersion,
|
|
CHAR nLevel
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Creates a new MOF_INFO with given data.
|
|
|
|
Arguments:
|
|
|
|
guid - Event GUID.
|
|
nType - Event type.
|
|
nVersion - Event version.
|
|
nLevel - Event level (not supported in this program).
|
|
|
|
Return Value:
|
|
|
|
Pointer to the created MOF_INFO. NULL if malloc failed.
|
|
|
|
--*/
|
|
{
|
|
PMOF_INFO pMofInfo;
|
|
|
|
pMofInfo = (PMOF_INFO)malloc(sizeof(MOF_INFO));
|
|
|
|
if( NULL == pMofInfo ){
|
|
return NULL;
|
|
}
|
|
|
|
RtlZeroMemory(pMofInfo, sizeof(MOF_INFO));
|
|
|
|
memcpy(&pMofInfo->Guid, &guid, sizeof(GUID) );
|
|
|
|
pMofInfo->ItemHeader = (PLIST_ENTRY)malloc(sizeof(LIST_ENTRY));
|
|
|
|
if( NULL == pMofInfo->ItemHeader ){
|
|
free( pMofInfo );
|
|
return NULL;
|
|
}
|
|
|
|
InitializeListHead(pMofInfo->ItemHeader);
|
|
|
|
pMofInfo->TypeIndex = nType;
|
|
pMofInfo->Level = nLevel;
|
|
pMofInfo->Version = nVersion;
|
|
|
|
return pMofInfo;
|
|
}
|
|
|
|
void
|
|
FlushMofList(
|
|
PLIST_ENTRY ListHead
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Flushes MOF_INFOs in a temporary list into the global list.
|
|
|
|
Arguments:
|
|
|
|
ListHead - Pointer to the head of a temporary list.
|
|
|
|
Return Value:
|
|
|
|
None.
|
|
|
|
--*/
|
|
{
|
|
PMOF_INFO pMofInfo;
|
|
PLIST_ENTRY Head = ListHead;
|
|
PLIST_ENTRY Next = Head->Flink;
|
|
|
|
while( Head != Next ){
|
|
pMofInfo = CONTAINING_RECORD(Next, MOF_INFO, Entry);
|
|
Next = Next->Flink;
|
|
|
|
RemoveEntryList(&pMofInfo->Entry);
|
|
InsertTailList( EventListHead, &pMofInfo->Entry);
|
|
}
|
|
}
|
|
|
|
HRESULT
|
|
WbemConnect(
|
|
IWbemServices** pWbemServices
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Connects to WBEM and returns a pointer to WbemServices.
|
|
|
|
Arguments:
|
|
|
|
pWbemServices - Pointer to the connected WbemServices.
|
|
|
|
Return Value:
|
|
|
|
ERROR_SUCCESS if successful. Error flag otherwise.
|
|
|
|
--*/
|
|
{
|
|
IWbemLocator *pLocator = NULL;
|
|
|
|
BSTR bszNamespace = SysAllocString( L"root\\wmi" );
|
|
|
|
HRESULT hr = CoInitialize(0);
|
|
|
|
hr = CoCreateInstance(
|
|
CLSID_WbemLocator,
|
|
0,
|
|
CLSCTX_INPROC_SERVER,
|
|
IID_IWbemLocator,
|
|
(LPVOID *) &pLocator
|
|
);
|
|
if ( ERROR_SUCCESS != hr )
|
|
goto cleanup;
|
|
|
|
hr = pLocator->ConnectServer(
|
|
bszNamespace,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
0L,
|
|
NULL,
|
|
NULL,
|
|
pWbemServices
|
|
);
|
|
if ( ERROR_SUCCESS != hr )
|
|
goto cleanup;
|
|
|
|
hr = CoSetProxyBlanket(
|
|
*pWbemServices,
|
|
RPC_C_AUTHN_WINNT,
|
|
RPC_C_AUTHZ_NONE,
|
|
NULL,
|
|
RPC_C_AUTHN_LEVEL_PKT,
|
|
RPC_C_IMP_LEVEL_IMPERSONATE,
|
|
NULL,
|
|
EOAC_NONE
|
|
);
|
|
|
|
cleanup:
|
|
SysFreeString( bszNamespace );
|
|
|
|
if( pLocator ){
|
|
pLocator->Release();
|
|
pLocator = NULL;
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
ULONG GetArraySize(
|
|
IN IWbemQualifierSet *pQualSet
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Examines a given qualifier set and returns the array size.
|
|
|
|
NOTE: WBEM stores the size of an array in "MAX" qualifier.
|
|
|
|
Arguments:
|
|
|
|
pQualSet - Pointer to a qualifier set.
|
|
|
|
Return Value:
|
|
|
|
The size of the array. The default is 1.
|
|
|
|
--*/
|
|
{
|
|
ULONG ArraySize = 1;
|
|
VARIANT pVal;
|
|
BSTR bszMaxLen;
|
|
HRESULT hRes;
|
|
|
|
if (pQualSet == NULL){
|
|
return ArraySize;
|
|
}
|
|
|
|
bszMaxLen = SysAllocString(L"MAX");
|
|
VariantInit(&pVal);
|
|
hRes = pQualSet->Get(bszMaxLen,
|
|
0,
|
|
&pVal,
|
|
0);
|
|
SysFreeString(bszMaxLen);
|
|
if (ERROR_SUCCESS == hRes && pVal.vt == VT_I4 ){
|
|
ArraySize = pVal.lVal;
|
|
}
|
|
VariantClear(&pVal);
|
|
return ArraySize;
|
|
}
|
|
|
|
ITEM_TYPE
|
|
GetItemType(
|
|
IN CIMTYPE_ENUMERATION CimType,
|
|
IN IWbemQualifierSet *pQualSet
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Examines a given qualifier set for a property and returns the type.
|
|
|
|
Arguments:
|
|
|
|
CimType - WBEM type (different from ITEM_TYPE) of a property.
|
|
pQualSet - Pointer to a qualifier set for a property under consideration.
|
|
|
|
Return Value:
|
|
|
|
The type (in ITEM_TYPE) of a property.
|
|
|
|
--*/
|
|
{
|
|
ITEM_TYPE Type;
|
|
VARIANT pVal;
|
|
HRESULT hRes;
|
|
BSTR bszQualName;
|
|
WCHAR strFormat[10];
|
|
WCHAR strTermination[30];
|
|
WCHAR strTemp[30];
|
|
BOOLEAN IsPointer = FALSE;
|
|
|
|
strFormat[0] = '\0';
|
|
strTermination[0] = '\0';
|
|
strTemp[0] = '\0';
|
|
|
|
if (pQualSet == NULL)
|
|
return ItemUnknown;
|
|
|
|
bszQualName = SysAllocString(L"format");
|
|
VariantInit(&pVal);
|
|
hRes = pQualSet->Get(bszQualName,
|
|
0,
|
|
&pVal,
|
|
0);
|
|
SysFreeString(bszQualName);
|
|
if (ERROR_SUCCESS == hRes && NULL != pVal.bstrVal)
|
|
wcscpy(strFormat, pVal.bstrVal);
|
|
|
|
bszQualName = SysAllocString(L"StringTermination");
|
|
VariantClear(&pVal);
|
|
hRes = pQualSet->Get(bszQualName,
|
|
0,
|
|
&pVal,
|
|
0);
|
|
SysFreeString(bszQualName);
|
|
if (ERROR_SUCCESS == hRes && NULL != pVal.bstrVal)
|
|
wcscpy(strTermination, pVal.bstrVal);
|
|
|
|
bszQualName = SysAllocString(L"pointer");
|
|
VariantClear(&pVal);
|
|
hRes = pQualSet->Get(bszQualName,
|
|
0,
|
|
&pVal,
|
|
0);
|
|
SysFreeString(bszQualName);
|
|
if (ERROR_SUCCESS == hRes)
|
|
IsPointer = TRUE;
|
|
// Major fix required to get rid of temp
|
|
bszQualName = SysAllocString(L"extension");
|
|
VariantClear(&pVal);
|
|
hRes = pQualSet->Get(bszQualName,
|
|
0,
|
|
&pVal,
|
|
0);
|
|
SysFreeString(bszQualName);
|
|
if (ERROR_SUCCESS == hRes && NULL != pVal.bstrVal)
|
|
wcscpy(strTemp, pVal.bstrVal);
|
|
|
|
VariantClear(&pVal);
|
|
|
|
CimType = (CIMTYPE_ENUMERATION)(CimType & (~CIM_FLAG_ARRAY));
|
|
|
|
switch (CimType) {
|
|
case CIM_EMPTY:
|
|
Type = ItemUnknown;
|
|
break;
|
|
case CIM_SINT8:
|
|
Type = ItemCharShort;
|
|
if (!_wcsicmp(strFormat, L"c")){
|
|
Type = ItemChar;
|
|
}
|
|
break;
|
|
case CIM_UINT8:
|
|
Type = ItemUChar;
|
|
break;
|
|
case CIM_SINT16:
|
|
Type = ItemShort;
|
|
break;
|
|
case CIM_UINT16:
|
|
Type = ItemUShort;
|
|
break;
|
|
case CIM_SINT32:
|
|
Type = ItemLong;
|
|
break;
|
|
case CIM_UINT32:
|
|
Type = ItemULong;
|
|
if (!_wcsicmp(strFormat, L"x")){
|
|
Type = ItemULongX;
|
|
}
|
|
break;
|
|
case CIM_SINT64:
|
|
Type = ItemLongLong;
|
|
break;
|
|
case CIM_UINT64:
|
|
Type = ItemULongLong;
|
|
break;
|
|
case CIM_REAL32:
|
|
Type = ItemFloat;
|
|
break;
|
|
case CIM_REAL64:
|
|
Type = ItemDouble;
|
|
break;
|
|
case CIM_BOOLEAN:
|
|
// ItemBool
|
|
Type = ItemBool;
|
|
break;
|
|
case CIM_STRING:
|
|
|
|
if (!_wcsicmp(strTermination, L"NullTerminated")) {
|
|
if (!_wcsicmp(strFormat, L"w"))
|
|
Type = ItemWString;
|
|
else
|
|
Type = ItemString;
|
|
}
|
|
else if (!_wcsicmp(strTermination, L"Counted")) {
|
|
if (!_wcsicmp(strFormat, L"w"))
|
|
Type = ItemPWString;
|
|
else
|
|
Type = ItemPString;
|
|
}
|
|
else if (!_wcsicmp(strTermination, L"ReverseCounted")) {
|
|
if (!_wcsicmp(strFormat, L"w"))
|
|
Type = ItemDSWString;
|
|
else
|
|
Type = ItemDSString;
|
|
}
|
|
else if (!_wcsicmp(strTermination, L"NotCounted")) {
|
|
Type = ItemNWString;
|
|
}else{
|
|
Type = ItemString;
|
|
}
|
|
break;
|
|
case CIM_CHAR16:
|
|
// ItemWChar
|
|
Type = ItemWChar;
|
|
break;
|
|
|
|
case CIM_OBJECT :
|
|
if (!_wcsicmp(strTemp, L"Port"))
|
|
Type = ItemPort;
|
|
// end_sdk
|
|
else if (!_wcsicmp(strTemp, L"RString"))
|
|
Type = ItemRString;
|
|
else if (!_wcsicmp(strTemp, L"RWString"))
|
|
Type = ItemRWString;
|
|
// begin_sdk
|
|
else if (!_wcsicmp(strTemp, L"IPAddr"))
|
|
Type = ItemIPAddr;
|
|
else if (!_wcsicmp(strTemp, L"Sid"))
|
|
Type = ItemSid;
|
|
else if (!_wcsicmp(strTemp, L"Guid"))
|
|
Type = ItemGuid;
|
|
// end_sdk
|
|
else if (!_wcsicmp(strTemp, L"Variant"))
|
|
Type = ItemVariant;
|
|
// begin_sdk
|
|
break;
|
|
|
|
case CIM_DATETIME:
|
|
case CIM_REFERENCE:
|
|
case CIM_ILLEGAL:
|
|
default:
|
|
Type = ItemUnknown;
|
|
break;
|
|
}
|
|
|
|
if (IsPointer)
|
|
Type = ItemPtr;
|
|
return Type;
|
|
}
|
|
|
|
PMOF_INFO
|
|
GetPropertiesFromWBEM(
|
|
IWbemClassObject *pTraceSubClasses,
|
|
GUID Guid,
|
|
SHORT nVersion,
|
|
CHAR nLevel,
|
|
SHORT nType
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Constructs a linked list with the information read from the WBEM
|
|
namespace, given the WBEM pointer to the version subtree. It enumerates
|
|
through all type classes in WBEM, and constructs MOF_INFOs for all of
|
|
them (for caching purpose). Meanwhile, it looks for the event layout
|
|
that mathces the passed event, and returns the pointer to the matching
|
|
MOF_INFO at the end.
|
|
|
|
Arguments:
|
|
|
|
pTraceSubClasses - WBEM pointer to the version subtree.
|
|
Guid - GUID of the passed event.
|
|
nVersion - version of the passed event.
|
|
nLevel - level of the passed event.
|
|
nType - type of the passed event.
|
|
|
|
Return Value:
|
|
|
|
Pointer to MOF_INFO corresponding to the passed event.
|
|
If the right type is not found, it returns the pointer to
|
|
the generic MOF_INFO for the event version.
|
|
|
|
--*/
|
|
{
|
|
IEnumWbemClassObject *pEnumTraceSubSubClasses = NULL;
|
|
IWbemClassObject *pTraceSubSubClasses = NULL;
|
|
IWbemQualifierSet *pQualSet = NULL;
|
|
|
|
PMOF_INFO pMofInfo = NULL, pMofLookup = NULL, pMofTemplate = NULL;
|
|
|
|
BSTR bszClassName = NULL;
|
|
BSTR bszSubClassName = NULL;
|
|
BSTR bszWmiDataId = NULL;
|
|
BSTR bszEventType = NULL;
|
|
BSTR bszEventTypeName = NULL;
|
|
BSTR bszFriendlyName = NULL;
|
|
BSTR bszPropName = NULL;
|
|
|
|
TCHAR strClassName[MAXSTR];
|
|
TCHAR strType[MAXSTR];
|
|
#ifndef UNICODE
|
|
CHAR TempString[MAXSTR];
|
|
#endif
|
|
LONG pVarType;
|
|
SHORT nEventType = EVENT_TYPE_DEFAULT;
|
|
|
|
LIST_ENTRY ListHead;
|
|
HRESULT hRes;
|
|
|
|
VARIANT pVal;
|
|
VARIANT pTypeVal;
|
|
VARIANT pTypeNameVal;
|
|
VARIANT pClassName;
|
|
ULONG lEventTypeWbem;
|
|
ULONG HUGEP *pTypeData;
|
|
BSTR HUGEP *pTypeNameData;
|
|
|
|
SAFEARRAY *PropArray = NULL;
|
|
SAFEARRAY *TypeArray = NULL;
|
|
SAFEARRAY *TypeNameArray = NULL;
|
|
|
|
long lLower, lUpper, lCount, IdIndex;
|
|
long lTypeLower, lTypeUpper;
|
|
long lTypeNameLower, lTypeNameUpper;
|
|
|
|
ULONG ArraySize;
|
|
|
|
ITEM_TYPE ItemType;
|
|
|
|
InitializeListHead(&ListHead);
|
|
|
|
VariantInit(&pVal);
|
|
VariantInit(&pTypeVal);
|
|
VariantInit(&pTypeNameVal);
|
|
VariantInit(&pClassName);
|
|
|
|
bszClassName = SysAllocString(L"__CLASS");
|
|
bszWmiDataId = SysAllocString(L"WmiDataId");
|
|
bszEventType = SysAllocString(L"EventType");
|
|
bszEventTypeName = SysAllocString(L"EventTypeName");
|
|
bszFriendlyName = SysAllocString(L"DisplayName");
|
|
|
|
hRes = pTraceSubClasses->Get(bszClassName, // property name
|
|
0L,
|
|
&pVal, // output to this variant
|
|
NULL,
|
|
NULL);
|
|
|
|
if (ERROR_SUCCESS == hRes){
|
|
if (pQualSet) {
|
|
pQualSet->Release();
|
|
pQualSet = NULL;
|
|
}
|
|
// Get Qualifier Set to obtain the friendly name.
|
|
pTraceSubClasses->GetQualifierSet(&pQualSet);
|
|
hRes = pQualSet->Get(bszFriendlyName,
|
|
0,
|
|
&pClassName,
|
|
0);
|
|
if (ERROR_SUCCESS == hRes && pClassName.bstrVal != NULL) {
|
|
#ifdef UNICODE
|
|
wcscpy(strClassName, pClassName.bstrVal);
|
|
#else
|
|
WideCharToMultiByte(CP_ACP,
|
|
0,
|
|
pClassName.bstrVal,
|
|
wcslen(pClassName.bstrVal),
|
|
TempString,
|
|
(MAXSTR * sizeof(CHAR)),
|
|
NULL,
|
|
NULL
|
|
);
|
|
strcpy(strClassName, TempString);
|
|
strClassName[wcslen(pClassName.bstrVal)] = '\0';
|
|
#endif
|
|
}
|
|
else {
|
|
#ifdef UNICODE
|
|
strClassName[0] = L'\0';
|
|
#else
|
|
strClassName[0] = '\0';
|
|
#endif
|
|
}
|
|
// Put Event Header
|
|
pMofInfo = GetNewMofInfo(Guid,
|
|
EVENT_TYPE_DEFAULT,
|
|
EVENT_VERSION_DEFAULT,
|
|
EVENT_LEVEL_DEFAULT
|
|
);
|
|
if (pMofInfo != NULL) {
|
|
pMofTemplate = pMofInfo;
|
|
pMofLookup = pMofInfo;
|
|
InsertTailList(&ListHead, &pMofInfo->Entry);
|
|
pMofInfo->strDescription = (LPTSTR)malloc((_tcslen(strClassName) + 1) * sizeof(TCHAR));
|
|
if (NULL != pMofInfo->strDescription) {
|
|
_tcscpy(pMofInfo->strDescription, strClassName);
|
|
}
|
|
}
|
|
else{
|
|
goto cleanup;
|
|
}
|
|
|
|
// Create an enumerator to find derived classes.
|
|
bszSubClassName = SysAllocString(pVal.bstrVal);
|
|
hRes = pWbemServices->CreateClassEnum (
|
|
bszSubClassName, // class name
|
|
WBEM_FLAG_SHALLOW | WBEM_FLAG_USE_AMENDED_QUALIFIERS, // shallow search
|
|
NULL,
|
|
&pEnumTraceSubSubClasses
|
|
);
|
|
SysFreeString ( bszSubClassName );
|
|
if (ERROR_SUCCESS == hRes) {
|
|
ULONG uReturnedSub = 1;
|
|
|
|
while(uReturnedSub == 1){
|
|
// For each event in the subclass
|
|
pTraceSubSubClasses = NULL;
|
|
hRes = pEnumTraceSubSubClasses->Next(5000, // timeout in five seconds
|
|
1, // return just one instance
|
|
&pTraceSubSubClasses, // pointer to a Sub class
|
|
&uReturnedSub); // number obtained: one
|
|
if (ERROR_SUCCESS == hRes && uReturnedSub == 1) {
|
|
if (pQualSet) {
|
|
pQualSet->Release();
|
|
pQualSet = NULL;
|
|
}
|
|
// Get Qualifier Set.
|
|
pTraceSubSubClasses->GetQualifierSet(&pQualSet);
|
|
// Get Type number among Qualifiers
|
|
VariantClear(&pTypeVal);
|
|
hRes = pQualSet->Get(bszEventType,
|
|
0,
|
|
&pTypeVal,
|
|
0);
|
|
|
|
if (ERROR_SUCCESS == hRes) {
|
|
TypeArray = NULL;
|
|
TypeNameArray = NULL;
|
|
if (pTypeVal.vt & VT_ARRAY) { // EventType is an array
|
|
TypeArray = pTypeVal.parray;
|
|
VariantClear(&pTypeNameVal);
|
|
hRes = pQualSet->Get(bszEventTypeName,
|
|
0,
|
|
&pTypeNameVal,
|
|
0);
|
|
if ((ERROR_SUCCESS == hRes) && (pTypeNameVal.vt & VT_ARRAY)) {
|
|
TypeNameArray = pTypeNameVal.parray;
|
|
}
|
|
if (TypeArray != NULL) {
|
|
hRes = SafeArrayGetLBound(TypeArray, 1, &lTypeLower);
|
|
if (ERROR_SUCCESS != hRes) {
|
|
break;
|
|
}
|
|
hRes = SafeArrayGetUBound(TypeArray, 1, &lTypeUpper);
|
|
if (ERROR_SUCCESS != hRes) {
|
|
break;
|
|
}
|
|
if (lTypeUpper < 0) {
|
|
break;
|
|
}
|
|
SafeArrayAccessData(TypeArray, (void HUGEP **)&pTypeData );
|
|
|
|
if (TypeNameArray != NULL) {
|
|
hRes = SafeArrayGetLBound(TypeNameArray, 1, &lTypeNameLower);
|
|
if (ERROR_SUCCESS != hRes) {
|
|
break;
|
|
}
|
|
hRes = SafeArrayGetUBound(TypeNameArray, 1, &lTypeNameUpper);
|
|
if (ERROR_SUCCESS != hRes) {
|
|
break;
|
|
}
|
|
if (lTypeNameUpper < 0)
|
|
break;
|
|
SafeArrayAccessData(TypeNameArray, (void HUGEP **)&pTypeNameData );
|
|
}
|
|
|
|
for (lCount = lTypeLower; lCount <= lTypeUpper; lCount++) {
|
|
lEventTypeWbem = pTypeData[lCount];
|
|
nEventType = (SHORT)lEventTypeWbem;
|
|
pMofInfo = GetNewMofInfo(Guid, nEventType, nVersion, nLevel);
|
|
if (pMofInfo != NULL) {
|
|
InsertTailList(&ListHead, &pMofInfo->Entry);
|
|
if (pMofTemplate != NULL && pMofTemplate->strDescription != NULL) {
|
|
pMofInfo->strDescription = (LPTSTR)malloc((_tcslen(pMofTemplate->strDescription) + 1) * sizeof(TCHAR));
|
|
if (pMofInfo->strDescription != NULL) {
|
|
_tcscpy(pMofInfo->strDescription, pMofTemplate->strDescription);
|
|
}
|
|
}
|
|
if (nType == nEventType) {
|
|
// Type matched
|
|
pMofLookup = pMofInfo;
|
|
}
|
|
if (TypeNameArray != NULL) {
|
|
if ((lCount >= lTypeNameLower) && (lCount <= lTypeNameUpper)) {
|
|
pMofInfo->strType = (LPTSTR)malloc((wcslen((LPWSTR)pTypeNameData[lCount]) + 1) * sizeof(TCHAR));
|
|
if (pMofInfo->strType != NULL){
|
|
#ifdef UNICODE
|
|
wcscpy(pMofInfo->strType, (LPWSTR)(pTypeNameData[lCount]));
|
|
#else
|
|
WideCharToMultiByte(CP_ACP,
|
|
0,
|
|
(LPWSTR)(pTypeNameData[lCount]),
|
|
wcslen((LPWSTR)(pTypeNameData[lCount])),
|
|
TempString,
|
|
(MAXSTR * sizeof(CHAR)),
|
|
NULL,
|
|
NULL
|
|
);
|
|
TempString[wcslen((LPWSTR)(pTypeNameData[lCount]))] = '\0';
|
|
strcpy(pMofInfo->strType, TempString);
|
|
#endif
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
SafeArrayUnaccessData(TypeArray);
|
|
SafeArrayDestroy(TypeArray);
|
|
VariantInit(&pTypeVal);
|
|
if (TypeNameArray != NULL) {
|
|
SafeArrayUnaccessData(TypeNameArray);
|
|
SafeArrayDestroy(TypeNameArray);
|
|
VariantInit(&pTypeNameVal);
|
|
}
|
|
}
|
|
else {
|
|
// If the Types are not found, then bail
|
|
break;
|
|
}
|
|
}
|
|
else { // EventType is scalar
|
|
hRes = VariantChangeType(&pTypeVal, &pTypeVal, 0, VT_I2);
|
|
if (ERROR_SUCCESS == hRes)
|
|
nEventType = (SHORT)V_I2(&pTypeVal);
|
|
else
|
|
nEventType = (SHORT)V_I4(&pTypeVal);
|
|
|
|
VariantClear(&pTypeNameVal);
|
|
hRes = pQualSet->Get(bszEventTypeName,
|
|
0,
|
|
&pTypeNameVal,
|
|
0);
|
|
if (ERROR_SUCCESS == hRes) {
|
|
#ifdef UNICODE
|
|
wcscpy(strType, pTypeNameVal.bstrVal);
|
|
#else
|
|
WideCharToMultiByte(CP_ACP,
|
|
0,
|
|
pTypeNameVal.bstrVal,
|
|
wcslen(pTypeNameVal.bstrVal),
|
|
TempString,
|
|
(MAXSTR * sizeof(CHAR)),
|
|
NULL,
|
|
NULL
|
|
);
|
|
strcpy(strType, TempString);
|
|
strType[wcslen(pTypeNameVal.bstrVal)] = '\0';
|
|
#endif
|
|
}
|
|
else{
|
|
#ifdef UNICODE
|
|
strType[0] = L'\0';
|
|
#else
|
|
strType[0] = '\0';
|
|
#endif
|
|
}
|
|
|
|
pMofInfo = GetNewMofInfo(Guid, nEventType, nVersion, nLevel);
|
|
if (pMofInfo != NULL) {
|
|
InsertTailList(&ListHead, &pMofInfo->Entry);
|
|
if (pMofTemplate != NULL && pMofTemplate->strDescription != NULL) {
|
|
pMofInfo->strDescription = (LPTSTR)malloc((_tcslen(pMofTemplate->strDescription) + 1) * sizeof(TCHAR));
|
|
if (pMofInfo->strDescription != NULL) {
|
|
_tcscpy(pMofInfo->strDescription, pMofTemplate->strDescription);
|
|
}
|
|
}
|
|
if (nType == nEventType) {
|
|
// Type matched
|
|
pMofLookup = pMofInfo;
|
|
}
|
|
pMofInfo->strType = (LPTSTR)malloc((_tcslen(strType) + 1) * sizeof(TCHAR));
|
|
if (pMofInfo->strType != NULL){
|
|
_tcscpy(pMofInfo->strType, strType);
|
|
}
|
|
}
|
|
}
|
|
|
|
// Get event layout
|
|
VariantClear(&pVal);
|
|
IdIndex = 1;
|
|
V_VT(&pVal) = VT_I4;
|
|
V_I4(&pVal) = IdIndex;
|
|
// For each property
|
|
PropArray = NULL;
|
|
while (pTraceSubSubClasses->GetNames(bszWmiDataId, // only properties with WmiDataId qualifier
|
|
WBEM_FLAG_ONLY_IF_IDENTICAL,
|
|
&pVal, // WmiDataId number starting from 1
|
|
&PropArray) == WBEM_NO_ERROR) {
|
|
|
|
hRes = SafeArrayGetLBound(PropArray, 1, &lLower);
|
|
if (ERROR_SUCCESS != hRes) {
|
|
break;
|
|
}
|
|
hRes = SafeArrayGetUBound(PropArray, 1, &lUpper);
|
|
if (ERROR_SUCCESS != hRes) {
|
|
break;
|
|
}
|
|
if (lUpper < 0)
|
|
break;
|
|
// This loop will iterate just once.
|
|
for (lCount = lLower; lCount <= lUpper; lCount++) {
|
|
hRes = SafeArrayGetElement(PropArray, &lCount, &bszPropName);
|
|
if (ERROR_SUCCESS != hRes) {
|
|
break;
|
|
}
|
|
hRes = pTraceSubSubClasses->Get(bszPropName, // Property name
|
|
0L,
|
|
NULL,
|
|
&pVarType, // CIMTYPE of the property
|
|
NULL);
|
|
if (ERROR_SUCCESS != hRes) {
|
|
break;
|
|
}
|
|
|
|
// Get the Qualifier set for the property
|
|
if (pQualSet) {
|
|
pQualSet->Release();
|
|
pQualSet = NULL;
|
|
}
|
|
hRes = pTraceSubSubClasses->GetPropertyQualifierSet(bszPropName,
|
|
&pQualSet);
|
|
|
|
if (ERROR_SUCCESS != hRes) {
|
|
break;
|
|
}
|
|
|
|
ItemType = GetItemType((CIMTYPE_ENUMERATION)pVarType, pQualSet);
|
|
|
|
if( pVarType & CIM_FLAG_ARRAY ){
|
|
ArraySize = GetArraySize(pQualSet);
|
|
}else{
|
|
ArraySize = 1;
|
|
}
|
|
#ifdef UNICODE
|
|
AddMofInfo(&ListHead,
|
|
bszPropName,
|
|
ItemType,
|
|
ArraySize);
|
|
#else
|
|
WideCharToMultiByte(CP_ACP,
|
|
0,
|
|
bszPropName,
|
|
wcslen(bszPropName),
|
|
TempString,
|
|
(MAXSTR * sizeof(CHAR)),
|
|
NULL,
|
|
NULL
|
|
);
|
|
TempString[wcslen(bszPropName)] = '\0';
|
|
AddMofInfo(&ListHead,
|
|
TempString,
|
|
ItemType,
|
|
ArraySize);
|
|
#endif
|
|
}
|
|
SafeArrayDestroy(PropArray);
|
|
PropArray = NULL;
|
|
V_I4(&pVal) = ++IdIndex;
|
|
} // end enumerating through WmiDataId
|
|
FlushMofList(&ListHead);
|
|
} // if getting event type was successful
|
|
} // if enumeration returned a subclass successfully
|
|
} // end enumerating subclasses
|
|
} // if enumeration was created successfully
|
|
} // if getting class name was successful
|
|
cleanup:
|
|
VariantClear(&pVal);
|
|
VariantClear(&pTypeVal);
|
|
VariantClear(&pClassName);
|
|
|
|
SysFreeString(bszClassName);
|
|
SysFreeString(bszWmiDataId);
|
|
SysFreeString(bszEventType);
|
|
SysFreeString(bszEventTypeName);
|
|
SysFreeString(bszFriendlyName);
|
|
// Should not free bszPropName becuase it is already freed by SafeArrayDestroy
|
|
|
|
FlushMofList(&ListHead);
|
|
|
|
return pMofLookup;
|
|
}
|
|
|
|
PMOF_INFO
|
|
GetGuids (GUID Guid,
|
|
SHORT nVersion,
|
|
CHAR nLevel,
|
|
SHORT nType
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Aceesses the MOF data information from WBEM, creates a linked list,
|
|
and returns a pointer that matches the passed event.
|
|
This function finds the right subtree within the WBEM namespace,
|
|
and calls GetPropertiesFromWBEM() to create the list.
|
|
|
|
Arguments:
|
|
|
|
Guid - GUID of the passed event.
|
|
nVersion - version of the passed event.
|
|
nLevel - level of the passed event.
|
|
nType - type of the passed event.
|
|
|
|
Return Value:
|
|
|
|
PMOF_INFO to MOF_INFO structure that matches the passed event.
|
|
NULL if no match is found.
|
|
|
|
--*/
|
|
{
|
|
IEnumWbemClassObject *pEnumTraceSubClasses = NULL, *pEnumTraceSubSubClasses = NULL;
|
|
IWbemClassObject *pTraceSubClasses = NULL, *pTraceSubSubClasses = NULL;
|
|
IWbemQualifierSet *pQualSet = NULL;
|
|
|
|
BSTR bszInstance = NULL;
|
|
BSTR bszPropertyName = NULL;
|
|
BSTR bszSubClassName = NULL;
|
|
BSTR bszGuid = NULL;
|
|
BSTR bszVersion = NULL;
|
|
|
|
WCHAR strGuid[MAXSTR], strTargetGuid[MAXSTR];
|
|
|
|
HRESULT hRes;
|
|
|
|
VARIANT pVal;
|
|
VARIANT pGuidVal;
|
|
VARIANT pVersionVal;
|
|
|
|
UINT nCounter=0;
|
|
BOOLEAN MatchFound;
|
|
SHORT nEventVersion = EVENT_VERSION_DEFAULT;
|
|
|
|
PMOF_INFO pMofLookup = NULL;
|
|
|
|
VariantInit(&pVal);
|
|
VariantInit(&pGuidVal);
|
|
VariantInit(&pVersionVal);
|
|
|
|
if (NULL == pWbemServices) {
|
|
hRes = WbemConnect( &pWbemServices );
|
|
if ( ERROR_SUCCESS != hRes ) {
|
|
goto cleanup;
|
|
}
|
|
}
|
|
|
|
// Convert traget GUID to string for later comparison
|
|
#ifdef UNICODE
|
|
GuidToString(strTargetGuid, &Guid);
|
|
#else
|
|
CHAR TempString[MAXSTR];
|
|
GuidToString(TempString, &Guid);
|
|
MultiByteToWideChar(CP_ACP, 0, TempString, -1, strTargetGuid, MAXSTR);
|
|
#endif
|
|
|
|
bszInstance = SysAllocString(L"EventTrace");
|
|
bszPropertyName = SysAllocString(L"__CLASS");
|
|
bszGuid = SysAllocString(L"Guid");
|
|
bszVersion = SysAllocString(L"EventVersion");
|
|
pEnumTraceSubClasses = NULL;
|
|
|
|
// Get an enumerator for all classes under "EventTace".
|
|
hRes = pWbemServices->CreateClassEnum (
|
|
bszInstance,
|
|
WBEM_FLAG_SHALLOW | WBEM_FLAG_USE_AMENDED_QUALIFIERS,
|
|
NULL,
|
|
&pEnumTraceSubClasses );
|
|
SysFreeString (bszInstance);
|
|
|
|
if (ERROR_SUCCESS == hRes) {
|
|
ULONG uReturned = 1;
|
|
MatchFound = FALSE;
|
|
while (uReturned == 1) {
|
|
pTraceSubClasses = NULL;
|
|
// Get the next ClassObject.
|
|
hRes = pEnumTraceSubClasses->Next(5000, // timeout in five seconds
|
|
1, // return just one instance
|
|
&pTraceSubClasses, // pointer to Event Trace Sub Class
|
|
&uReturned); // number obtained: one or zero
|
|
if (ERROR_SUCCESS == hRes && (uReturned == 1)) {
|
|
// Get the class name
|
|
hRes = pTraceSubClasses->Get(bszPropertyName, // property name
|
|
0L,
|
|
&pVal, // output to this variant
|
|
NULL,
|
|
NULL);
|
|
if (ERROR_SUCCESS == hRes){
|
|
bszSubClassName = SysAllocString(pVal.bstrVal);
|
|
// Create an enumerator to find derived classes.
|
|
hRes = pWbemServices->CreateClassEnum (
|
|
bszSubClassName,
|
|
WBEM_FLAG_SHALLOW | WBEM_FLAG_USE_AMENDED_QUALIFIERS,
|
|
NULL,
|
|
&pEnumTraceSubSubClasses
|
|
);
|
|
SysFreeString ( bszSubClassName );
|
|
bszSubClassName = NULL;
|
|
VariantClear(&pVal);
|
|
|
|
if (ERROR_SUCCESS == hRes) {
|
|
|
|
ULONG uReturnedSub = 1;
|
|
while(uReturnedSub == 1){
|
|
|
|
pTraceSubSubClasses = NULL;
|
|
// enumerate through the resultset.
|
|
hRes = pEnumTraceSubSubClasses->Next(5000, // timeout in five seconds
|
|
1, // return just one instance
|
|
&pTraceSubSubClasses, // pointer to a Sub class
|
|
&uReturnedSub); // number obtained: one or zero
|
|
if (ERROR_SUCCESS == hRes && uReturnedSub == 1) {
|
|
// Get the subclass name
|
|
hRes = pTraceSubSubClasses->Get(bszPropertyName, // Class name
|
|
0L,
|
|
&pVal, // output to this variant
|
|
NULL,
|
|
NULL);
|
|
VariantClear(&pVal);
|
|
|
|
if (ERROR_SUCCESS == hRes){
|
|
// Get Qualifier Set.
|
|
if (pQualSet) {
|
|
pQualSet->Release();
|
|
pQualSet = NULL;
|
|
}
|
|
pTraceSubSubClasses->GetQualifierSet (&pQualSet );
|
|
|
|
// Get GUID among Qualifiers
|
|
hRes = pQualSet->Get(bszGuid,
|
|
0,
|
|
&pGuidVal,
|
|
0);
|
|
if (ERROR_SUCCESS == hRes) {
|
|
wcscpy(strGuid, (LPWSTR)V_BSTR(&pGuidVal));
|
|
VariantClear ( &pGuidVal );
|
|
|
|
if (!wcsstr(strGuid, L"{"))
|
|
swprintf(strGuid , L"{%s}", strGuid);
|
|
|
|
if (!_wcsicmp(strTargetGuid, strGuid)) {
|
|
hRes = pQualSet->Get(bszVersion,
|
|
0,
|
|
&pVersionVal,
|
|
0);
|
|
if (ERROR_SUCCESS == hRes) {
|
|
hRes = VariantChangeType(&pVersionVal, &pVersionVal, 0, VT_I2);
|
|
if (ERROR_SUCCESS == hRes)
|
|
nEventVersion = (SHORT)V_I2(&pVersionVal);
|
|
else
|
|
nEventVersion = (SHORT)V_I4(&pVersionVal);
|
|
VariantClear(&pVersionVal);
|
|
|
|
if (nVersion == nEventVersion) {
|
|
// Match is found.
|
|
// Now put all events in this subtree into the list
|
|
MatchFound = TRUE;
|
|
pMofLookup = GetPropertiesFromWBEM( pTraceSubSubClasses,
|
|
Guid,
|
|
nVersion,
|
|
nLevel,
|
|
nType
|
|
);
|
|
break;
|
|
}
|
|
}
|
|
else {
|
|
// if there is no version number for this event,
|
|
// the current one is the only one
|
|
// Now put all events in this subtree into the list
|
|
MatchFound = TRUE;
|
|
pMofLookup = GetPropertiesFromWBEM( pTraceSubSubClasses,
|
|
Guid,
|
|
EVENT_VERSION_DEFAULT,
|
|
nLevel,
|
|
nType
|
|
);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
} // end while enumerating sub classes
|
|
if (MatchFound) {
|
|
break;
|
|
}
|
|
if (pEnumTraceSubSubClasses) {
|
|
pEnumTraceSubSubClasses->Release();
|
|
pEnumTraceSubSubClasses = NULL;
|
|
}
|
|
} // if creating enumeration was successful
|
|
else {
|
|
pEnumTraceSubSubClasses = NULL;
|
|
}
|
|
} // if getting class name was successful
|
|
}
|
|
nCounter++;
|
|
// if match is found, break out of the top level search
|
|
if (MatchFound)
|
|
break;
|
|
} // end while enumerating top classes
|
|
if( pEnumTraceSubClasses ){
|
|
pEnumTraceSubClasses->Release();
|
|
pEnumTraceSubClasses = NULL;
|
|
}
|
|
} // if creating enumeration for top level is successful
|
|
|
|
cleanup:
|
|
|
|
VariantClear(&pGuidVal);
|
|
VariantClear(&pVersionVal);
|
|
|
|
SysFreeString(bszGuid);
|
|
SysFreeString(bszPropertyName);
|
|
SysFreeString(bszVersion);
|
|
|
|
if( pEnumTraceSubClasses ){
|
|
pEnumTraceSubClasses->Release();
|
|
pEnumTraceSubClasses = NULL;
|
|
}
|
|
if (pEnumTraceSubSubClasses){
|
|
pEnumTraceSubSubClasses->Release();
|
|
pEnumTraceSubSubClasses = NULL;
|
|
}
|
|
if (pQualSet) {
|
|
pQualSet->Release();
|
|
pQualSet = NULL;
|
|
}
|
|
|
|
return pMofLookup;
|
|
}
|
|
|
|
ULONG
|
|
ahextoi(
|
|
TCHAR *s
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Converts a hex number to an integer.
|
|
|
|
Arguments:
|
|
|
|
s - Input string containing a hex number.
|
|
|
|
Return Value:
|
|
|
|
ULONG denoted by the hex string s.
|
|
|
|
--*/
|
|
{
|
|
long len;
|
|
ULONG num, base, hex;
|
|
|
|
if (s == NULL)
|
|
return 0;
|
|
if (*s == 0)
|
|
return 0;
|
|
len = (long) _tcslen(s);
|
|
if (len == 0 || len >= MAXSTR )
|
|
return 0;
|
|
hex = 0; base = 1; num = 0;
|
|
while (--len >= 0) {
|
|
if ( (s[len] == 'x' || s[len] == 'X') &&
|
|
(s[len-1] == '0') )
|
|
break;
|
|
if (s[len] >= '0' && s[len] <= '9')
|
|
num = s[len] - '0';
|
|
else if (s[len] >= 'a' && s[len] <= 'f')
|
|
num = (s[len] - 'a') + 10;
|
|
else if (s[len] >= 'A' && s[len] <= 'F')
|
|
num = (s[len] - 'A') + 10;
|
|
else
|
|
continue;
|
|
|
|
hex += num * base;
|
|
base = base * 16;
|
|
}
|
|
return hex;
|
|
}
|
|
|
|
void
|
|
RemoveWhiteSpace(
|
|
TCHAR *s
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Removes white space (' ', '\n', and '\t') from the given string.
|
|
|
|
Arguments:
|
|
|
|
s - Input and output string.
|
|
|
|
Return Value:
|
|
|
|
None
|
|
|
|
--*/
|
|
{
|
|
UINT i = 0;
|
|
UINT j = 0;
|
|
TCHAR TempString[MAXSTR];
|
|
if (s == NULL)
|
|
return;
|
|
_tcscpy(TempString, s);
|
|
while (TempString[i] != '\0') {
|
|
if (TempString[i] != ' ' && TempString[i] != '\t' && TempString[i] != '\n')
|
|
s[j++] = TempString[i];
|
|
++i;
|
|
}
|
|
s[j] = '\0';
|
|
}
|
|
// end_sdk
|
|
void
|
|
DisplayVersionInfo()
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
prints out a version information.
|
|
|
|
Arguments:
|
|
|
|
None.
|
|
|
|
Return Value:
|
|
|
|
None.
|
|
|
|
|
|
--*/
|
|
{
|
|
TCHAR buffer[512];
|
|
TCHAR strProgram[MAXSTR];
|
|
DWORD dw;
|
|
BYTE* pVersionInfo;
|
|
LPTSTR pVersion = NULL;
|
|
LPTSTR pProduct = NULL;
|
|
LPTSTR pCopyRight = NULL;
|
|
|
|
dw = GetModuleFileName(NULL, strProgram, MAXSTR);
|
|
|
|
if( dw>0 ){
|
|
|
|
dw = GetFileVersionInfoSize( strProgram, &dw );
|
|
if( dw > 0 ){
|
|
|
|
pVersionInfo = (BYTE*)malloc(dw);
|
|
if( NULL != pVersionInfo ){
|
|
if(GetFileVersionInfo( strProgram, 0, dw, pVersionInfo )){
|
|
LPDWORD lptr = NULL;
|
|
VerQueryValue( pVersionInfo, _T("\\VarFileInfo\\Translation"), (void**)&lptr, (UINT*)&dw );
|
|
if( lptr != NULL ){
|
|
_stprintf( buffer, _T("\\StringFileInfo\\%04x%04x\\%s"), LOWORD(*lptr), HIWORD(*lptr), _T("ProductVersion") );
|
|
VerQueryValue( pVersionInfo, buffer, (void**)&pVersion, (UINT*)&dw );
|
|
_stprintf( buffer, _T("\\StringFileInfo\\%04x%04x\\%s"), LOWORD(*lptr), HIWORD(*lptr), _T("OriginalFilename") );
|
|
VerQueryValue( pVersionInfo, buffer, (void**)&pProduct, (UINT*)&dw );
|
|
_stprintf( buffer, _T("\\StringFileInfo\\%04x%04x\\%s"), LOWORD(*lptr), HIWORD(*lptr), _T("LegalCopyright") );
|
|
VerQueryValue( pVersionInfo, buffer, (void**)&pCopyRight, (UINT*)&dw );
|
|
}
|
|
|
|
if( pProduct != NULL && pVersion != NULL && pCopyRight != NULL ){
|
|
_tprintf( _T("\nMicrosoft (R) %s (%s)\n%s\n\n"), pProduct, pVersion, pCopyRight );
|
|
}
|
|
}
|
|
free( pVersionInfo );
|
|
}
|
|
}
|
|
}
|
|
}
|
|
// begin_sdk
|
|
void
|
|
PrintHelpMessage()
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Prints out help messages.
|
|
|
|
Arguments:
|
|
|
|
None
|
|
|
|
Return Value:
|
|
|
|
None
|
|
|
|
--*/
|
|
{
|
|
// end_sdk
|
|
DisplayVersionInfo();
|
|
// begin_sdk
|
|
_tprintf(
|
|
_T("Usage: tracedmp [options] <EtlFile1 EtlFile2 ...>| [-h | -? | -help]\n")
|
|
_T("\t-o <file> Output CSV file\n")
|
|
_T("\t-rt [LoggerName] Realtime tracedmp from the logger [LoggerName]\n")
|
|
_T("\t-summary Summary.txt only\n")
|
|
_T("\t-begin HH:MM DD/MM/YY\n")
|
|
_T("\t-end HH:MM DD/MM/YY\n")
|
|
_T("\t-h\n")
|
|
_T("\t-help\n")
|
|
_T("\t-? Display usage information\n")
|
|
_T("\n")
|
|
_T("\tDefault Etl File is C:\\Logfile.etl\n")
|
|
_T("\tDefault output file is dumpfile.csv\n")
|
|
);
|
|
}
|
|
|
|
// end_sdk
|