windows-nt/Source/XPSP1/NT/public/internal/base/inc/winperfp.h

480 lines
17 KiB
C
Raw Normal View History

2020-09-26 03:20:57 -05:00
/*++
Copyright (c) Microsoft Corporation. All rights reserved.
Module Name:
winperfp.h
Abstract:
Private header file used by various internal components related to perflib
and associated tools.
NOTE: At least one source file must include this with _INIT_WINPERFP_ defined
and also include <initguid.h> so that storage for global variables and
proper routines are included.
To use debug tracing, just call WinPerfStartTrace(hKey), where hKey can be
an opened key to HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Perflib.
If hKey is NULL, the routine will open it automatically.
--*/
#ifndef _WINPERFP_H_
#define _WINPERFP_H_
#if _MSC_VER > 1000
#pragma once
#endif
#include <pshpack8.h>
#include <setupbat.h>
// Increasing debug trace levels. Higher level always includes tracing lower levels.
#define WINPERF_DBG_TRACE_NONE 0 // no trace
#define WINPERF_DBG_TRACE_FATAL 1 // Print fatal error traces only
#define WINPERF_DBG_TRACE_ERROR 2 // All errors
#define WINPERF_DBG_TRACE_WARNING 3 // Warnings as well
#define WINPERF_DBG_TRACE_INFO 4 // Informational traces as well
#define WINPERF_DBG_TRACE_ALL 255 // All traces
// Data structure definitions.
//
// PERFLIB Tracing routines definition. Starts from 10
//
#define PERF_OPEN_KEY 10 // PerfOpenKey
#define PERF_REG_QUERY_VALUE 11 // PerfRegQueryValue
#define PERF_REG_CLOSE_KEY 12 // PerfRegCloseKey
#define PERF_REG_SET_VALUE 13 // PerfRegSetValue
#define PERG_REG_ENUM_KEY 14 // PerfRegEnumKey
#define PERF_REG_QUERY_INFO_KEY 15 // PerfRegQueryInfoKey
#define PERF_REG_ENUM_VALUE 16 // PerfRegEnumValue
#define PERF_ENUM_TEXT_VALUE 17 // PerfEnumTextValue
#define PERF_ALLOC_INIT_EXT 18 // AllocateAndInitializeExtObject
#define PERF_OPEN_EXT_OBJS 19 // OpenExtensibleObjects
#define PERF_SERVICE_IS_TRUSTED 20 // ServiceIsTrustedByDefault
#define PERF_CLOSE_EXTOBJLIB 21 // CloseExtObjectLibrary
#define PERF_OPEN_EXTOBJLIB 22 // OpenExtObjectLibrary
#define PERF_QUERY_EXTDATA 23 // QueryExtensibleData
#define PERF_GET_NAMES 24 // PerfGetNames
#define PERF_GET_PERFLIBVALUE 25 // GetPerflibKeyValue
#define PERF_TIMER_FUNCTION 26 // PerflibTimerFunction
#define PERF_START_TIMER_FUNCTION 27 // StartPerflibFunctionTimer
#define PERF_DESTROY_TIMER_FUNCTION 28 // DestroyPerflibFunctionTimer
#define PERF_GET_DDLINFO 29 // GetPerfDllFileInfo
#define PERF_DISABLE_PERFLIB 30 // DisablePerfLibrary
#define PERF_DISABLE_LIBRARY 31 // DisableLibrary
#define PERF_UPDATE_ERROR_COUNT 32 // PerfUpdateErrorCount
#define PERF_TIMERFUNCTION 33
#define PERF_STARTFUNCTIONTIMER 34
#define PERF_KILLFUNCTIONTIMER 35
#define PERF_DESTROYFUNCTIONTIMER 36
// LOADPERF trace routine definition, starts from 10
//
#define LOADPERF_DLLENTRYPOINT 10
#define LOADPERF_GETSTRINGRESOURCE 11
#define LOADPERF_GETFORMATRESOURCE 12
#define LOADPERF_DISPLAYCOMMANDHELP 13
#define LOADPERF_TRIMSPACES 14
#define LOADPERF_ISDELIMITER 15
#define LOADPERF_GETITEMFROMSTRING 16
#define LOADPERF_REPORTLOADPERFEVENT 17
#define LOADPERF_LOADPERFGRABMUTEX 18
#define LOADPERF_LOADPERFSTARTEVENTLOG 19
#define LOADPERF_LOADPERFDBGTRACE 20
#define LOADPERF_VERIFYREGISTRY 21
#define LOADPERF_SIGNALWMIWITHNEWDATA 25
#define LOADPERF_LODCTRCOMPILEMOFFILE 26
#define LOADPERF_LODCTRCOMPILEMOFBUFFER 27
#define LOADPERF_DUMPNAMETABLE 30
#define LOADPERF_DUMPPERFSERVICEENTRIES 31
#define LOADPERF_DUMPPERFLIBENTRIES 32
#define LOADPERF_BUILDSERVICELISTS 33
#define LOADPERF_BACKUPPERFREGISTRYTOFILEW 34
#define LOADPERF_RESTOREPERFREGISTRYFROMFILEW 35
#define LOADPERF_FORMATPERFNAME 40
#define LOADPERF_GETPERFTYPEINFO 41
#define LOADPERF_GETPERFOBJECTGUID 42
#define LOADPERF_GENERATEMOFHEADER 43
#define LOADPERF_GENERATEMOFOBJECT 44
#define LOADPERF_GENERATEMOFOBJECTTAIL 45
#define LOADPERF_GENERATEMOFCOUNTER 46
#define LOADPERF_GENERATEMOFINSTANCES 47
#define LOADPERF_UNLODCTR_BUILDNAMETABLE 50
#define LOADPERF_GETDRIVERFROMCOMMANDLINE 51
#define LOADPERF_FIXNAMES 52
#define LOADPERF_UNLOADCOUNTERNAMES 53
#define LOADPERF_UNLOADPERFCOUNTERTEXTSTRINGS 54
#define LOADPERF_MAKETEMPFILENAME 60
#define LOADPERF_WRITEWIDESTRINGTOANSIFILE 61
#define LOADPERF_LODCTR_BUILDNAMETABLE 62
#define LOADPERF_MAKEBACKUPCOPYOFLANGUAGEFILES 63
#define LOADPERF_GETFILEFROMCOMMANDLINE 64
#define LOADPERF_LODCTRSERSERVICEASTRUSTED 65
#define LOADPERF_GETDRIVERNAME 66
#define LOADPERF_BUILDLANGUAGETABLES 67
#define LOADPERF_LOADINCLUDEFILE 68
#define LOADPERF_PARSETEXTID 69
#define LOADPERF_FINDLANGUAGE 70
#define LOADPERF_GETVALUE 71
#define LOADPERF_GETVALUEFROMINIKEY 72
#define LOADPERF_ADDENTRYTOLANGUAGE 73
#define LOADPERF_CREATEOBJECTLIST 74
#define LOADPERF_LOADLANGUAGELISTS 75
#define LOADPERF_SORTLANGUAGETABLES 76
#define LOADPERF_GETINSTALLEDLANGUAGELIST 77
#define LOADPERF_CHECKNAMETABLE 78
#define LOADPERF_UPDATEEACHLANGUAGE 79
#define LOADPERF_UPDATEREGISTRY 80
#define LOADPERF_GETMOFFILEFROMINI 81
#define LOADPERF_OPENCOUNTERANDBUILDMOFFILE 82
#define LOADPERF_INSTALLPERFDLL 83
#define LOADPERF_LOADPERFCOUNTERTEXTSTRINGS 84
#define LOADPERF_LOADMOFFROMINSTALLEDSERVICE 85
#define LOADPERF_UPDATEPERFNAMEFILES 86
#define LOADPERF_SETSERVICEASTRUSTED 87
//
// Convenient macros to determine string sizes
//
// Macro to compute the actual size of a WCHAR or DBCS string
#define WSTRSIZE(str) (ULONG) ( (str) ? ((PCHAR) &str[wcslen(str)] - (PCHAR)str) + sizeof(UNICODE_NULL) : 0 )
#define STRSIZE(str) (ULONG) ( (str) ? ((PCHAR) &str[strlen(str)] - (PCHAR)str) + 1 : 0 )
#define TRACE_WSTR(str) str, WSTRSIZE(str)
#define TRACE_STR(str) str, STRSIZE(str)
#define TRACE_DWORD(dwValue) & dwValue, sizeof(dwValue)
//
// For debug tracing
//
#define TRACE(L, X) if (g_dwTraceLevel >= L) WinPerfDbgTrace X
VOID
WinPerfDbgTrace(
IN LPCGUID Guid,
IN ULONG LineNumber,
IN ULONG ModuleNumber,
IN ULONG OptArgs,
IN ULONG Status,
...
);
#define ARG_TYPE_ULONG 0
#define ARG_TYPE_WSTR 1
#define ARG_TYPE_STR 2
#define ARG_TYPE_ULONG64 3
// n must be 1 through 8. x is the one of above types
#define ARG_DEF(x, n) (x << ((n-1) * 4))
ULONG
WinPerfStartTrace(
IN HKEY hKey
);
DEFINE_GUID( /* 51af3adb-28b1-4ba5-b59a-3aeec16deb3c */
PerflibGuid,
0x51af3adb,
0x28b1,
0x4ba5,
0xb5, 0x9a, 0x3a, 0xee, 0xc1, 0x6d, 0xeb, 0x3c
);
DEFINE_GUID( /* 275a79bb-9980-42ba-bafe-a92ded1192cf */
LoadPerfGuid,
0x275a79bb,
0x9980,
0x42ba,
0xba, 0xfe, 0xa9, 0x2d, 0xed, 0x11, 0x92, 0xcf);
extern const WCHAR cszTraceLevel[];
extern const WCHAR cszTraceLogName[];
extern const WCHAR cszTraceFileValue[];
extern const WCHAR cszDefaultTraceFileName[];
extern TRACEHANDLE g_hTraceHandle;
extern DWORD g_dwTraceLevel;
#ifdef _PERFLIB_H_
#define WinperfQueryValueEx(a,b,c,d,e,f) \
PrivateRegQueryValueExT(a, (LPVOID)b, c, d, e, f, TRUE)
#else
#define WinperfQueryValueEx RegQueryValueExW
#endif
//
// Below is necessary for global variables and routine to
// be included to each dll or exe
//
#ifdef _INIT_WINPERFP_
const WCHAR cszTraceLevel[] = L"DebugTraceLevel";
const WCHAR cszTraceFileValue[] = L"DebugTraceFile";
const WCHAR cszPerfDebugTraceLevel[] = L"PerfDebugTraceLevel";
const WCHAR cszTraceLogName[] = L"PerfDbg Logger";
const WCHAR cszDefaultTraceFile[] = L"PerfDbg.Etl";
const WCHAR cszDefaultTraceFileName[] = L"C:\\perfdbg.etl";
TRACEHANDLE g_hTraceHandle = 0;
DWORD g_dwTraceLevel = WINPERF_DBG_TRACE_NONE;
LONG g_lDbgStarted = 0;
ULONG
WinPerfStartTrace(
IN HKEY hKey // Key to Perflib or NULL
)
{
CHAR Buffer[1024];
PCHAR ptr;
DWORD status, dwType, dwSize;
PEVENT_TRACE_PROPERTIES Properties;
TRACEHANDLE TraceHandle;
DWORD bLocalKey = 0;
WCHAR FileName[MAX_PATH + 1];
LPWSTR szTraceFileName = NULL;
ULONG lFileNameSize = 0;
DWORD dwTraceLevel = WINPERF_DBG_TRACE_NONE;
HKEY hKeySetup;
DWORD dwUpgradeType = 0;
DWORD dwSetupInProgress = 0;
if (InterlockedCompareExchange(& g_lDbgStarted, 1, 0) != 0) {
return g_dwTraceLevel;
}
status = RegOpenKeyExW(HKEY_LOCAL_MACHINE,
L"SYSTEM\\Setup",
0L,
KEY_READ,
& hKeySetup);
if (status == ERROR_SUCCESS) {
dwSize = sizeof(DWORD);
dwType = 0;
status = WinperfQueryValueEx(hKeySetup,
L"SystemSetupInProgress",
NULL,
& dwType,
(LPBYTE) & dwSetupInProgress,
& dwSize);
if (status == ERROR_SUCCESS && dwType == REG_DWORD
&& dwSetupInProgress != 0) {
// System setup in progress, check whether "PerfDebugTraceLevel"
// is defined in [UserData] section of setup answer file
// $winnt$.inf;
//
WCHAR szAnswerFile[MAX_PATH];
ZeroMemory(szAnswerFile, sizeof(WCHAR) * MAX_PATH);
GetSystemDirectoryW(szAnswerFile, MAX_PATH);
lstrcatW(szAnswerFile, L"\\");
lstrcatW(szAnswerFile, WINNT_GUI_FILE_W);
dwTraceLevel = GetPrivateProfileIntW(WINNT_USERDATA_W,
cszPerfDebugTraceLevel,
WINPERF_DBG_TRACE_NONE,
szAnswerFile);
#if 0
DbgPrint("GetPrivateProfileIntW(\"%ws\",\"%ws\",\"%ws\")(%d,%d)\n",
szAnswerFile,WINNT_USERDATA_W,cszPerfDebugTraceLevel,
dwTraceLevel, GetLastError());
#endif
}
CloseHandle(hKeySetup);
}
status = ERROR_SUCCESS;
if (dwTraceLevel == WINPERF_DBG_TRACE_NONE) {
if (hKey == NULL) {
status = RegOpenKeyExW (
HKEY_LOCAL_MACHINE,
L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Perflib",
0L,
KEY_READ,
& hKey);
bLocalKey = TRUE;
}
if (status == ERROR_SUCCESS) {
dwSize = sizeof(DWORD);
dwType = 0;
status = WinperfQueryValueEx(hKey,
cszTraceLevel,
NULL,
& dwType,
(LPBYTE) & dwTraceLevel,
& dwSize);
if ((status != ERROR_SUCCESS) || (dwType != REG_DWORD)) {
dwTraceLevel = WINPERF_DBG_TRACE_NONE;
if (bLocalKey) {
CloseHandle(hKey);
}
}
}
}
if (dwTraceLevel == WINPERF_DBG_TRACE_NONE)
return WINPERF_DBG_TRACE_NONE;
dwType = 0;
dwSize = (MAX_PATH + 1) * sizeof(WCHAR);
status = WinperfQueryValueEx(hKey,
cszTraceFileValue,
NULL,
&dwType,
(LPBYTE) FileName,
&dwSize);
if (bLocalKey) {
CloseHandle(hKey);
}
if ((status == ERROR_SUCCESS) && (dwType == REG_SZ)) {
szTraceFileName = & FileName[0];
lFileNameSize = WSTRSIZE(FileName);
}
else {
if (GetSystemWindowsDirectoryW(FileName, MAX_PATH) > 0) {
lstrcatW(FileName, L"\\");
lstrcatW(FileName, cszDefaultTraceFile);
szTraceFileName = & FileName[0];
lFileNameSize = WSTRSIZE(FileName);
}
else {
szTraceFileName = (LPWSTR) &cszDefaultTraceFileName[0];
lFileNameSize = sizeof(cszDefaultTraceFileName);
}
}
g_dwTraceLevel = dwTraceLevel;
RtlZeroMemory(Buffer, 1024);
Properties = (PEVENT_TRACE_PROPERTIES) &Buffer[0];
Properties->Wnode.BufferSize = 1024;
Properties->Wnode.Flags = WNODE_FLAG_TRACED_GUID;
Properties->LoggerNameOffset = sizeof(EVENT_TRACE_PROPERTIES);
Properties->LogFileNameOffset = Properties->LoggerNameOffset +
sizeof(cszTraceLogName);
ptr = (PCHAR) ((PCHAR) &Buffer[0] + Properties->LoggerNameOffset);
RtlCopyMemory(ptr, cszTraceLogName, sizeof(cszTraceLogName));
ptr = (PCHAR) ((PCHAR) &Buffer[0] + Properties->LogFileNameOffset);
RtlCopyMemory(ptr, szTraceFileName, lFileNameSize);
status = QueryTraceW(0, cszTraceLogName, Properties);
if (status == ERROR_SUCCESS) {
g_hTraceHandle = (TRACEHANDLE) Properties->Wnode.HistoricalContext;
return dwTraceLevel;
}
//
// Reinitialize structure again for StartTrace()
//
RtlZeroMemory(Buffer, 1024);
Properties->Wnode.BufferSize = 1024;
Properties->Wnode.Flags = WNODE_FLAG_TRACED_GUID;
Properties->BufferSize = 64;
Properties->LogFileMode = EVENT_TRACE_FILE_MODE_SEQUENTIAL |
EVENT_TRACE_USE_PAGED_MEMORY |
EVENT_TRACE_FILE_MODE_APPEND;
Properties->LoggerNameOffset = sizeof(EVENT_TRACE_PROPERTIES);
Properties->LogFileNameOffset = Properties->LoggerNameOffset +
sizeof(cszTraceLogName);
ptr = (PCHAR) ((PCHAR) &Buffer[0] + Properties->LoggerNameOffset);
RtlCopyMemory(ptr, cszTraceLogName, sizeof(cszTraceLogName));
ptr = (PCHAR) ((PCHAR) &Buffer[0] + Properties->LogFileNameOffset);
RtlCopyMemory(ptr, szTraceFileName, lFileNameSize);
status = StartTraceW(& TraceHandle, cszTraceLogName, Properties);
if (status == ERROR_SUCCESS) {
g_hTraceHandle = TraceHandle;
return dwTraceLevel;
}
g_dwTraceLevel = WINPERF_DBG_TRACE_NONE;
g_hTraceHandle = (TRACEHANDLE) 0;
return WINPERF_DBG_TRACE_NONE;
}
VOID
WinPerfDbgTrace(
IN LPCGUID Guid,
IN ULONG LineNumber,
IN ULONG ModuleNumber,
IN ULONG OptArgs,
IN ULONG Status,
...
)
{
ULONG ErrorCode;
struct _MY_EVENT {
EVENT_TRACE_HEADER Header;
MOF_FIELD MofField[MAX_MOF_FIELDS];
} MyEvent;
ULONG i;
va_list ArgList;
PVOID source;
SIZE_T len;
DWORD dwLastError;
dwLastError = GetLastError();
RtlZeroMemory(& MyEvent, sizeof(EVENT_TRACE_HEADER));
va_start(ArgList, Status);
for (i = 3; i < MAX_MOF_FIELDS; i ++) {
source = va_arg(ArgList, PVOID);
if (source == NULL)
break;
len = va_arg(ArgList, SIZE_T);
if (len == 0)
break;
MyEvent.MofField[i].DataPtr = (ULONGLONG) source;
MyEvent.MofField[i].Length = (ULONG) len;
}
va_end(ArgList);
MyEvent.Header.Class.Type = (UCHAR) ModuleNumber;
MyEvent.Header.Size = (USHORT) (sizeof(EVENT_TRACE_HEADER) + (i * sizeof(MOF_FIELD)));
MyEvent.Header.Flags = WNODE_FLAG_TRACED_GUID |
WNODE_FLAG_USE_MOF_PTR |
WNODE_FLAG_USE_GUID_PTR;
MyEvent.Header.GuidPtr = (ULONGLONG) Guid;
MyEvent.MofField[0].DataPtr = (ULONGLONG) &LineNumber;
MyEvent.MofField[0].Length = sizeof(LineNumber);
MyEvent.MofField[1].DataPtr = (ULONGLONG) &Status;
MyEvent.MofField[1].Length = sizeof(Status);
MyEvent.MofField[2].DataPtr = (ULONGLONG) &OptArgs;
MyEvent.MofField[2].Length = sizeof(OptArgs);
__try {
ErrorCode = TraceEvent(g_hTraceHandle, (PEVENT_TRACE_HEADER) & MyEvent);
// ErrorCode = TraceMessage(g_hTraceHandle, TRACE_FLAGS, (LPGUID) &PerflibGuid,
// ModuleNumber, ArgList);
} __except (EXCEPTION_EXECUTE_HANDLER) {
ErrorCode = GetLastError();
}
if (ErrorCode != ERROR_SUCCESS) {
/* Use the following to debug the trace statements that are failing
DbgPrint("ErrorCode=%d Module=%d Line %d Status 0X%X\n", ErrorCode, ModuleNumber,
LineNumber, Status); */
/* should continue tracing, no need to turn off
g_dwTraceLevel = WINPERF_DBG_TRACE_NONE;
g_hTraceHandle = (TRACEHANDLE) 0; */
}
SetLastError(dwLastError);
}
#endif // _INIT_WINPERFP_
#include <poppack.h>
#endif // _WINPERFP_H_