Добавлена папка source в CristalDiskMark

This commit is contained in:
2026-05-29 13:04:54 +07:00
commit bdc2295ee4
240 changed files with 94035 additions and 0 deletions
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,87 @@
/*
DISKSPD
Copyright(c) Microsoft Corporation
All rights reserved.
MIT License
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
#pragma once
#define INITGUID //Include this #define to use SystemTraceControlGuid in Evntrace.h.
#include <Evntrace.h> //ETW
#include <Winternl.h> //ntdll.dll
void PrintError(const char *format, ...);
void *ManagedMalloc(size_t size);
namespace UnitTests
{
class IORequestGeneratorUnitTests;
}
class IORequestGenerator
{
public:
IORequestGenerator() :
_hNTDLL(nullptr)
{
}
bool GenerateRequests(Profile& profile, IResultParser& resultParser, PRINTF pPrintOut, PRINTF pPrintError, PRINTF pPrintVerbose, struct Synchronization *pSynch, int *totalScore, double *averageLatency);
static UINT64 GetNextFileOffset(ThreadParameters& tp, size_t targetNum, UINT64 prevOffset);
static UINT64 GetStartingFileOffset(ThreadParameters& tp, size_t targetNum);
static UINT64 GetThreadBaseFileOffset(ThreadParameters& tp, size_t targetNum);
private:
struct CreateFileParameters
{
string sPath;
UINT64 ullFileSize;
bool fZeroWriteBuffers;
};
bool _GenerateRequestsForTimeSpan(const Profile& profile, const TimeSpan& timeSpan, Results& results, struct Synchronization *pSynch);
void _AbortWorkerThreads(HANDLE hStartEvent, vector<HANDLE>& vhThreads) const;
void _CloseOpenFiles(vector<HANDLE>& vhFiles) const;
DWORD _CreateDirectoryPath(const char *path) const;
bool _CreateFile(UINT64 ullFileSize, const char *pszFilename, bool fZeroBuffers, bool fVerbose) const;
void _DisplayFileSizeVerbose(bool fVerbose, UINT64 fsize) const;
bool _GetActiveGroupsAndProcs() const;
struct ETWSessionInfo _GetResultETWSession(const EVENT_TRACE_PROPERTIES *pTraceProperties) const;
bool _GetSystemPerfInfo(SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION *pInfo, UINT32 uCpuCount) const;
void _InitializeGlobalParameters();
bool _LoadDLLs();
bool _StopETW(bool fUseETW, TRACEHANDLE hTraceSession) const;
void _TerminateWorkerThreads(vector<HANDLE>& vhThreads) const;
bool _ValidateProfile(const Profile& profile) const;
vector<struct CreateFileParameters> _GetFilesToPrecreate(const Profile& profile) const;
void _MarkFilesAsCreated(Profile& profile, const vector<struct CreateFileParameters>& vFiles) const;
bool _PrecreateFiles(Profile& profile) const;
HINSTANCE volatile _hNTDLL; //handle to ntdll.dll
friend class UnitTests::IORequestGeneratorUnitTests;
};
@@ -0,0 +1,79 @@
/*
DISKSPD
Copyright(c) Microsoft Corporation
All rights reserved.
MIT License
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
#include "OverlappedQueue.h"
#include <assert.h>
OverlappedQueue::OverlappedQueue(void) :
_pHead(nullptr),
_pTail(nullptr),
_cItems(0)
{
}
void OverlappedQueue::Add(OVERLAPPED *pOverlapped)
{
pOverlapped->Internal = NULL;
if (_pHead == nullptr)
{
assert(_pTail == nullptr);
_pHead = pOverlapped;
}
else
{
assert(_pTail != nullptr);
_pTail->Internal = (ULONG_PTR)pOverlapped;
}
_pTail = pOverlapped;
_cItems++;
}
bool OverlappedQueue::IsEmpty(void) const
{
return (_pHead == nullptr);
}
OVERLAPPED *OverlappedQueue::Remove(void)
{
assert(!IsEmpty());
OVERLAPPED *pOverlapped = _pHead;
_pHead = (OVERLAPPED *)pOverlapped->Internal;
if (_pHead == nullptr)
{
_pTail = nullptr;
}
_cItems--;
return pOverlapped;
}
size_t OverlappedQueue::GetCount() const
{
return _cItems;
}
@@ -0,0 +1,50 @@
/*
DISKSPD
Copyright(c) Microsoft Corporation
All rights reserved.
MIT License
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
#pragma once
#include <Windows.h>
//
// OverlappedQueue is a simple class that implements a queue for OVERLAPPED elements
//
class OverlappedQueue
{
public:
OverlappedQueue(void);
void Add(OVERLAPPED *pOverlapped);
bool IsEmpty(void) const;
OVERLAPPED * Remove(void);
size_t GetCount() const;
private:
OVERLAPPED *_pHead;
OVERLAPPED *_pTail;
size_t _cItems;
};
@@ -0,0 +1,123 @@
/*
DISKSPD
Copyright(c) Microsoft Corporation
All rights reserved.
MIT License
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
#include "ThroughputMeter.h"
ThroughputMeter::ThroughputMeter(void) :
_fRunning(false)
{
}
bool ThroughputMeter::IsRunning(void) const
{
return _fRunning;
}
void ThroughputMeter::Start(DWORD cBytesPerMillisecond, DWORD dwBlockSize, DWORD dwThinkTime, DWORD dwBurstSize)
{
// Initialization
_cbCompleted = 0;
_cIO = 0; // number of completed IOs in the current burst
_cbBlockSize = dwBlockSize;
_fThrottle = false;
_cBytesPerMillisecond = 0;
_fThink = false;
_ullDelayUntil = 0;
_thinkTime = 0;
_burstSize = 0;
_fRunning = false;
/// GetTickCount64 -> GetTickCount
_ullStartTimestamp = GetTickCount();
if (0 != cBytesPerMillisecond)
{
_fThrottle = true;
_cBytesPerMillisecond = cBytesPerMillisecond;
_fRunning = true;
}
else if (0 != dwThinkTime)
{
_fThink = true;
_thinkTime = dwThinkTime;
_burstSize = dwBurstSize;
_fRunning = true;
}
}
DWORD ThroughputMeter::GetSleepTime(void) const
{
if (_fThink)
{
/// GetTickCount64 -> GetTickCount
ULONGLONG ullTimestamp = GetTickCount();
if (ullTimestamp < _ullDelayUntil)
{
return (DWORD)(_ullDelayUntil - ullTimestamp);
}
else
{
return (_fThrottle) ? _GetThrottleTime() : 0;
}
}
else
{
if (_fThrottle) // think time has not been specified only check for throttling
{
return _GetThrottleTime();
}
else
{
return 0;
}
}
}
DWORD ThroughputMeter::_GetThrottleTime(void) const
{
/// GetTickCount64 -> GetTickCount
ULONGLONG cbExpected = (GetTickCount() - _ullStartTimestamp) * _cBytesPerMillisecond;
return cbExpected >= (_cbCompleted + _cbBlockSize) ? 0 : 1;
}
void ThroughputMeter::Adjust(size_t cb)
{
_cbCompleted += cb;
_cIO++;
if (_fThink)
{
if (_cIO >= _burstSize)
{
_cIO = 0;
/// GetTickCount64 -> GetTickCount
_ullDelayUntil = GetTickCount() + _thinkTime;
}
}
}
@@ -0,0 +1,61 @@
/*
DISKSPD
Copyright(c) Microsoft Corporation
All rights reserved.
MIT License
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
#pragma once
#include <Windows.h>
// ThroughputMeter class assists in metering out throughput over
// time. The meter is started by calling Start() with the throughput
// to be simulated. GetSleepTime() returns 0 when the next IO can be issued.
// Adjust() is called to notify the ThroughputMeter about how many bytes were read/written.
class ThroughputMeter
{
public:
ThroughputMeter(void);
bool IsRunning(void) const;
void Start(DWORD cBytesPerMillisecond, DWORD dwBlockSize, DWORD dwThinkTime, DWORD dwBurstSize);
DWORD GetSleepTime(void) const;
void Adjust(size_t cb);
private:
DWORD _GetThrottleTime(void) const;
bool _fRunning; // true = throughput monitoring is on
bool _fThrottle; // true = throttling is on
bool _fThink; // true = think time is enabled
ULONGLONG _cbCompleted; // completed IO
DWORD _cbBlockSize;
DWORD _cBytesPerMillisecond; // rate of throttling
ULONGLONG _ullStartTimestamp;
ULONGLONG _ullDelayUntil; // timestamp at which the next IO can be executed
DWORD _thinkTime; // time to sleep between burst of IOs
DWORD _burstSize; // number of IOs in a burst. meaningless if think time is zero
DWORD _cIO; // count of IOs in the current burst
};
@@ -0,0 +1,502 @@
/*
DISKSPD
Copyright(c) Microsoft Corporation
All rights reserved.
MIT License
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
#include "etw.h"
#include "common.h"
#include <stdio.h>
#include <stdlib.h>
#include <Wmistr.h> //WNODE_HEADER
#define INITGUID //Include this #define to use SystemTraceControlGuid in Evntrace.h.
#include <Evntrace.h> //ETW
#include "IORequestGenerator.h"
// variables declared in IORequestGenerator.cpp
extern struct ETWEventCounters g_EtwEventCounters;
extern BOOL volatile g_bTracing;
DEFINE_GUID ( /* 3d6fa8d4-fe05-11d0-9dda-00c04fd7ba7c */
DiskIoGuid,
0x3d6fa8d4,
0xfe05,
0x11d0,
0x9d, 0xda, 0x00, 0xc0, 0x4f, 0xd7, 0xba, 0x7c
);
DEFINE_GUID ( /* 90cbdc39-4a3e-11d1-84f4-0000f80464e3 */
FileIoGuid,
0x90cbdc39,
0x4a3e,
0x11d1,
0x84, 0xf4, 0x00, 0x00, 0xf8, 0x04, 0x64, 0xe3
);
DEFINE_GUID ( /* 2cb15d1d-5fc1-11d2-abe1-00a0c911f518 */
ImageLoadGuid,
0x2cb15d1d,
0x5fc1,
0x11d2,
0xab, 0xe1, 0x00, 0xa0, 0xc9, 0x11, 0xf5, 0x18
);
DEFINE_GUID ( /* 3d6fa8d3-fe05-11d0-9dda-00c04fd7ba7c */
PageFaultGuid,
0x3d6fa8d3,
0xfe05,
0x11d0,
0x9d, 0xda, 0x00, 0xc0, 0x4f, 0xd7, 0xba, 0x7c
);
DEFINE_GUID ( /* 9a280ac0-c8e0-11d1-84e2-00c04fb998a2 */
TcpIpGuid,
0x9a280ac0,
0xc8e0,
0x11d1,
0x84, 0xe2, 0x00, 0xc0, 0x4f, 0xb9, 0x98, 0xa2
);
DEFINE_GUID ( /* bf3a50c5-a9c9-4988-a005-2df0b7c80f80 */
UdpIpGuid,
0xbf3a50c5,
0xa9c9,
0x4988,
0xa0, 0x05, 0x2d, 0xf0, 0xb7, 0xc8, 0x0f, 0x80
);
DEFINE_GUID ( /* 3d6fa8d0-fe05-11d0-9dda-00c04fd7ba7c */
ProcessGuid,
0x3d6fa8d0,
0xfe05,
0x11d0,
0x9d, 0xda, 0x00, 0xc0, 0x4f, 0xd7, 0xba, 0x7c
);
DEFINE_GUID ( /* AE53722E-C863-11d2-8659-00C04FA321A1 */
RegistryGuid,
0xae53722e,
0xc863,
0x11d2,
0x86, 0x59, 0x0, 0xc0, 0x4f, 0xa3, 0x21, 0xa1
);
DEFINE_GUID ( /* 3d6fa8d1-fe05-11d0-9dda-00c04fd7ba7c */
ThreadGuid,
0x3d6fa8d1,
0xfe05,
0x11d0,
0x9d, 0xda, 0x00, 0xc0, 0x4f, 0xd7, 0xba, 0x7c
);
/*****************************************************************************/
// consumes events' data
//
BOOL TraceEvents()
{
TRACEHANDLE handles[1];
EVENT_TRACE_LOGFILE logfile;
memset(&logfile, 0, sizeof(EVENT_TRACE_LOGFILE));
logfile.LoggerName = KERNEL_LOGGER_NAME;
logfile.LogFileName = NULL;
logfile.LogFileMode = EVENT_TRACE_REAL_TIME_MODE;
logfile.IsKernelTrace = true;
handles[0] = OpenTrace(&logfile);
if( (TRACEHANDLE)INVALID_HANDLE_VALUE == handles[0] )
{
PrintError("ETW ERROR: OpenTrace failed (error code: %d)\n", GetLastError());
return false;
}
else
{
ProcessTrace(handles, 1, 0, 0);
CloseTrace(handles[0]);
}
return true;
}
/*****************************************************************************/
// allocates memory for ETW properties structure
//
PEVENT_TRACE_PROPERTIES allocateEventTraceProperties()
{
PEVENT_TRACE_PROPERTIES pProperties = NULL;
size_t size = 0;
size = sizeof(EVENT_TRACE_PROPERTIES)+sizeof(KERNEL_LOGGER_NAME);
pProperties = (PEVENT_TRACE_PROPERTIES)malloc(size);
if( NULL == pProperties )
{
PrintError("FATAL ERROR: unable to allocate memory (error code: %d)\n", GetLastError());
return NULL;
}
memset(pProperties, 0, size);
pProperties->LoggerNameOffset = sizeof(EVENT_TRACE_PROPERTIES);
pProperties->Wnode.BufferSize = (ULONG)size;
pProperties->Wnode.Flags = WNODE_FLAG_TRACED_GUID;
strcpy_s((char *)pProperties+pProperties->LoggerNameOffset,
size-pProperties->LoggerNameOffset, KERNEL_LOGGER_NAME);
return pProperties;
}
/*****************************************************************************/
// callback function for disk I/O events
void WINAPI eventDiskIo(PEVENT_TRACE pEvent)
{
if( EVENT_TRACE_TYPE_IO_READ == pEvent->Header.Class.Type )
{
++g_EtwEventCounters.ullIORead;
}
else if( EVENT_TRACE_TYPE_IO_WRITE == pEvent->Header.Class.Type )
{
++g_EtwEventCounters.ullIOWrite;
}
}
/*****************************************************************************/
// callback function for LoadImage events
//
void WINAPI eventLoadImage(PEVENT_TRACE pEvent)
{
if( EVENT_TRACE_TYPE_LOAD == pEvent->Header.Class.Type )
{
++g_EtwEventCounters.ullImageLoad;
}
}
/*****************************************************************************/
// callback function for memory events
//
void WINAPI eventPageFault(PEVENT_TRACE pEvent)
{
if( EVENT_TRACE_TYPE_MM_COW == pEvent->Header.Class.Type )
{
++g_EtwEventCounters.ullMMCopyOnWrite;
}
else if( EVENT_TRACE_TYPE_MM_DZF == pEvent->Header.Class.Type )
{
++g_EtwEventCounters.ullMMDemandZeroFault;
}
else if( EVENT_TRACE_TYPE_MM_GPF == pEvent->Header.Class.Type )
{
++g_EtwEventCounters.ullMMGuardPageFault;
}
else if( EVENT_TRACE_TYPE_MM_HPF == pEvent->Header.Class.Type )
{
++g_EtwEventCounters.ullMMHardPageFault;
}
else if( EVENT_TRACE_TYPE_MM_TF == pEvent->Header.Class.Type )
{
++g_EtwEventCounters.ullMMTransitionFault;
}
}
/*****************************************************************************/
// callback function for network and TCP/IP events
//
void WINAPI eventTcpIp(PEVENT_TRACE pEvent)
{
if( EVENT_TRACE_TYPE_ACCEPT == pEvent->Header.Class.Type )
{
++g_EtwEventCounters.ullNetAccept;
}
else if( EVENT_TRACE_TYPE_CONNECT == pEvent->Header.Class.Type )
{
++g_EtwEventCounters.ullNetConnect;
}
else if( EVENT_TRACE_TYPE_DISCONNECT == pEvent->Header.Class.Type )
{
++g_EtwEventCounters.ullNetDisconnect;
}
else if( EVENT_TRACE_TYPE_RECEIVE == pEvent->Header.Class.Type )
{
++g_EtwEventCounters.ullNetTcpReceive;
}
else if( EVENT_TRACE_TYPE_RECONNECT == pEvent->Header.Class.Type )
{
++g_EtwEventCounters.ullNetReconnect;
}
else if( EVENT_TRACE_TYPE_RETRANSMIT == pEvent->Header.Class.Type )
{
++g_EtwEventCounters.ullNetRetransmit;
}
else if( EVENT_TRACE_TYPE_SEND == pEvent->Header.Class.Type )
{
++g_EtwEventCounters.ullNetTcpSend;
}
}
/*****************************************************************************/
// callback function for UDP/IP events
//
void WINAPI eventUdpIp(PEVENT_TRACE pEvent)
{
if( EVENT_TRACE_TYPE_SEND == pEvent->Header.Class.Type )
{
++g_EtwEventCounters.ullNetUdpSend;
}
else if( EVENT_TRACE_TYPE_RECEIVE == pEvent->Header.Class.Type )
{
++g_EtwEventCounters.ullNetUdpReceive;
}
}
/*****************************************************************************/
// callback function for thread events
//
void WINAPI eventThread(PEVENT_TRACE pEvent)
{
if( EVENT_TRACE_TYPE_START == pEvent->Header.Class.Type )
{
++g_EtwEventCounters.ullThreadStart;
}
else if( EVENT_TRACE_TYPE_END == pEvent->Header.Class.Type )
{
++g_EtwEventCounters.ullThreadEnd;
}
}
/*****************************************************************************/
// callback function for process events
//
void WINAPI eventProcess(PEVENT_TRACE pEvent)
{
if( EVENT_TRACE_TYPE_START == pEvent->Header.Class.Type )
{
++g_EtwEventCounters.ullProcessStart;
}
else if( EVENT_TRACE_TYPE_END == pEvent->Header.Class.Type )
{
++g_EtwEventCounters.ullProcessEnd;
}
}
/*****************************************************************************/
// callback function for registry events
//
void WINAPI eventRegistry(PEVENT_TRACE pEvent)
{
if( EVENT_TRACE_TYPE_REGCREATE == pEvent->Header.Class.Type )
{
++g_EtwEventCounters.ullRegCreate;
}
else if( EVENT_TRACE_TYPE_REGDELETE == pEvent->Header.Class.Type )
{
++g_EtwEventCounters.ullRegDelete;
}
else if( EVENT_TRACE_TYPE_REGDELETEVALUE == pEvent->Header.Class.Type )
{
++g_EtwEventCounters.ullRegDeleteValue;
}
else if( EVENT_TRACE_TYPE_REGENUMERATEKEY == pEvent->Header.Class.Type )
{
++g_EtwEventCounters.ullRegEnumerateKey;
}
else if( EVENT_TRACE_TYPE_REGENUMERATEVALUEKEY == pEvent->Header.Class.Type )
{
++g_EtwEventCounters.ullRegEnumerateValueKey;
}
else if( EVENT_TRACE_TYPE_REGFLUSH == pEvent->Header.Class.Type )
{
++g_EtwEventCounters.ullRegFlush;
}
// else if( EVENT_TRACE_TYPE_REGKCBDMP == pEvent->Header.Class.Type )
// {
// ++ETWEventCounters.ullRegKcbDmp;
// }
else if( EVENT_TRACE_TYPE_REGOPEN == pEvent->Header.Class.Type )
{
++g_EtwEventCounters.ullRegOpen;
}
else if( EVENT_TRACE_TYPE_REGQUERY == pEvent->Header.Class.Type )
{
++g_EtwEventCounters.ullRegQuery;
}
else if( EVENT_TRACE_TYPE_REGQUERYMULTIPLEVALUE == pEvent->Header.Class.Type )
{
++g_EtwEventCounters.ullRegQueryMultipleValue;
}
else if( EVENT_TRACE_TYPE_REGQUERYVALUE == pEvent->Header.Class.Type )
{
++g_EtwEventCounters.ullRegQueryValue;
}
else if( EVENT_TRACE_TYPE_REGSETINFORMATION == pEvent->Header.Class.Type )
{
++g_EtwEventCounters.ullRegSetInformation;
}
else if( EVENT_TRACE_TYPE_REGSETVALUE == pEvent->Header.Class.Type )
{
++g_EtwEventCounters.ullRegSetValue;
}
}
/*****************************************************************************/
// starts ETW session and sets callback functions for various groups of events
//
TRACEHANDLE StartETWSession(const Profile& profile)
{
PEVENT_TRACE_PROPERTIES pProperties;
pProperties = allocateEventTraceProperties();
if (nullptr == pProperties)
{
return 0;
}
pProperties->LogFileMode = EVENT_TRACE_REAL_TIME_MODE;
//use paged memory
if (profile.GetEtwUsePagedMemory())
{
pProperties->LogFileMode |= EVENT_TRACE_USE_PAGED_MEMORY;
}
//
// event classes
//
if (profile.GetEtwProcess())
{
pProperties->EnableFlags |= EVENT_TRACE_FLAG_PROCESS;
SetTraceCallback(&ProcessGuid, eventThread);
}
if (profile.GetEtwThread())
{
pProperties->EnableFlags |= EVENT_TRACE_FLAG_THREAD;
SetTraceCallback(&ThreadGuid, eventThread);
}
if (profile.GetEtwImageLoad())
{
pProperties->EnableFlags |= EVENT_TRACE_FLAG_IMAGE_LOAD;
SetTraceCallback(&ImageLoadGuid, eventLoadImage);
}
if (profile.GetEtwDiskIO())
{
pProperties->EnableFlags |= EVENT_TRACE_FLAG_DISK_IO;
SetTraceCallback(&DiskIoGuid, eventDiskIo);
}
if (profile.GetEtwMemoryPageFaults())
{
pProperties->EnableFlags |= EVENT_TRACE_FLAG_MEMORY_PAGE_FAULTS;
SetTraceCallback(&PageFaultGuid, eventPageFault);
}
if (profile.GetEtwMemoryHardFaults())
{
pProperties->EnableFlags |= EVENT_TRACE_FLAG_MEMORY_HARD_FAULTS;
SetTraceCallback(&PageFaultGuid, eventPageFault);
}
if (profile.GetEtwNetwork())
{
pProperties->EnableFlags |= EVENT_TRACE_FLAG_NETWORK_TCPIP;
SetTraceCallback(&TcpIpGuid, eventTcpIp);
SetTraceCallback(&UdpIpGuid, eventUdpIp);
}
if (profile.GetEtwRegistry())
{
pProperties->EnableFlags |= EVENT_TRACE_FLAG_REGISTRY;
SetTraceCallback(&RegistryGuid, eventRegistry);
}
//
// timer
//
if (profile.GetEtwUsePerfTimer())
{
pProperties->Wnode.ClientContext = 1;
}
if (profile.GetEtwUseSystemTimer())
{
pProperties->Wnode.ClientContext = 2;
}
if (profile.GetEtwUseCyclesCounter())
{
pProperties->Wnode.ClientContext = 3;
}
pProperties->Wnode.Guid = SystemTraceControlGuid;
TRACEHANDLE hTraceSession;
ULONG ret = StartTrace(&hTraceSession, KERNEL_LOGGER_NAME, pProperties);
free(pProperties);
if (ERROR_SUCCESS != ret)
{
PrintError("Error starting trace session\n");
return 0;
}
return hTraceSession;
}
/*****************************************************************************/
// stops ETW session
//
PEVENT_TRACE_PROPERTIES StopETWSession(TRACEHANDLE hTraceSession)
{
PEVENT_TRACE_PROPERTIES pProperties;
pProperties = allocateEventTraceProperties();
if( NULL == pProperties )
{
return NULL;
}
ULONG ret;
ret = ControlTrace(hTraceSession, NULL, pProperties, EVENT_TRACE_CONTROL_STOP);
if( ERROR_SUCCESS != ret )
{
PrintError("Error stopping trace session\n");
return NULL;
}
//wait
while(g_bTracing)
{
Sleep(10); // TODO: remove active waiting
}
return pProperties;
}
@@ -0,0 +1,41 @@
/*
DISKSPD
Copyright(c) Microsoft Corporation
All rights reserved.
MIT License
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
#pragma once
#include <windows.h>
#include <Wmistr.h> ///WNODE_HEADER
#define INITGUID //Include this #define to use SystemTraceControlGuid in Evntrace.h.
#include <Evntrace.h> //ETW
#include "..\Common\Common.h"
BOOL TraceEvents();
TRACEHANDLE StartETWSession(const Profile& profile);
PEVENT_TRACE_PROPERTIES StopETWSession(TRACEHANDLE hTraceSession);