上传文件
This commit is contained in:
commit
b0065a876c
10
.gitignore
vendored
Normal file
10
.gitignore
vendored
Normal file
@ -0,0 +1,10 @@
|
||||
################################################################################
|
||||
# 此 .gitignore 文件已由 Microsoft(R) Visual Studio 自动创建。
|
||||
################################################################################
|
||||
/.vs
|
||||
/*.user
|
||||
/*.filters
|
||||
/x64/*
|
||||
/*.log
|
||||
/*.zip
|
||||
|
||||
31
MemoryCheck.sln
Normal file
31
MemoryCheck.sln
Normal file
@ -0,0 +1,31 @@
|
||||
|
||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
# Visual Studio Version 17
|
||||
VisualStudioVersion = 17.7.34003.232
|
||||
MinimumVisualStudioVersion = 10.0.40219.1
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "MemoryCheck", "MemoryCheck.vcxproj", "{EB6DCBDD-4D65-45BB-BD45-AB1D3C41C09C}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|x64 = Debug|x64
|
||||
Debug|x86 = Debug|x86
|
||||
Release|x64 = Release|x64
|
||||
Release|x86 = Release|x86
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{EB6DCBDD-4D65-45BB-BD45-AB1D3C41C09C}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{EB6DCBDD-4D65-45BB-BD45-AB1D3C41C09C}.Debug|x64.Build.0 = Debug|x64
|
||||
{EB6DCBDD-4D65-45BB-BD45-AB1D3C41C09C}.Debug|x86.ActiveCfg = Debug|Win32
|
||||
{EB6DCBDD-4D65-45BB-BD45-AB1D3C41C09C}.Debug|x86.Build.0 = Debug|Win32
|
||||
{EB6DCBDD-4D65-45BB-BD45-AB1D3C41C09C}.Release|x64.ActiveCfg = Release|x64
|
||||
{EB6DCBDD-4D65-45BB-BD45-AB1D3C41C09C}.Release|x64.Build.0 = Release|x64
|
||||
{EB6DCBDD-4D65-45BB-BD45-AB1D3C41C09C}.Release|x86.ActiveCfg = Release|Win32
|
||||
{EB6DCBDD-4D65-45BB-BD45-AB1D3C41C09C}.Release|x86.Build.0 = Release|Win32
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
EndGlobalSection
|
||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||
SolutionGuid = {8025197E-75FD-46DE-ADCE-CF6408D1F8DD}
|
||||
EndGlobalSection
|
||||
EndGlobal
|
||||
160
MemoryCheck.vcxproj
Normal file
160
MemoryCheck.vcxproj
Normal file
@ -0,0 +1,160 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup Label="ProjectConfigurations">
|
||||
<ProjectConfiguration Include="Debug|Win32">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|Win32">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Debug|x64">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|x64">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
</ItemGroup>
|
||||
<PropertyGroup Label="Globals">
|
||||
<VCProjectVersion>17.0</VCProjectVersion>
|
||||
<Keyword>Win32Proj</Keyword>
|
||||
<ProjectGuid>{eb6dcbdd-4d65-45bb-bd45-ab1d3c41c09c}</ProjectGuid>
|
||||
<RootNamespace>MemoryCheck</RootNamespace>
|
||||
<WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<PlatformToolset>v143</PlatformToolset>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<PlatformToolset>v143</PlatformToolset>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<PlatformToolset>v143</PlatformToolset>
|
||||
<CharacterSet>MultiByte</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<PlatformToolset>v143</PlatformToolset>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<CharacterSet>MultiByte</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||
<ImportGroup Label="ExtensionSettings">
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="Shared">
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<PropertyGroup Label="UserMacros" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<IncludePath>$(ProjectDir)include\easylog;$(ProjectDir)include\INIH;$(IncludePath)</IncludePath>
|
||||
<IntDir>$(Platform)\$(Configuration)obj\</IntDir>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<IntDir>$(Platform)\$(Configuration)obj\</IntDir>
|
||||
<IncludePath>$(ProjectDir)include\easylog;$(ProjectDir)include\INIH;$(IncludePath)</IncludePath>
|
||||
</PropertyGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<ConformanceMode>true</ConformanceMode>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Console</SubSystem>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<ConformanceMode>true</ConformanceMode>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Console</SubSystem>
|
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<PreprocessorDefinitions>_DEBUG;_CONSOLE;WIN32_LEAN_AND_MEAN;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<ConformanceMode>true</ConformanceMode>
|
||||
<MultiProcessorCompilation>true</MultiProcessorCompilation>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Windows</SubSystem>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<AdditionalDependencies>rpcrt4.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<PreprocessorDefinitions>NDEBUG;_CONSOLE;WIN32_LEAN_AND_MEAN;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<ConformanceMode>true</ConformanceMode>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Windows</SubSystem>
|
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<AdditionalDependencies>rpcrt4.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="include\easylog\easylogging++.cc" />
|
||||
<ClCompile Include="include\INIH\ini.c" />
|
||||
<ClCompile Include="include\INIH\INIReader.cpp" />
|
||||
<ClCompile Include="main.cpp" />
|
||||
<ClCompile Include="src\MemoryCheck.cpp" />
|
||||
<ClCompile Include="utils\StringHelper.cpp" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="include\easylog\easylogging++.h" />
|
||||
<ClInclude Include="include\INIH\ini.h" />
|
||||
<ClInclude Include="include\INIH\INIReader.h" />
|
||||
<ClInclude Include="src\Config.h" />
|
||||
<ClInclude Include="src\MemDefine.h" />
|
||||
<ClInclude Include="src\MemoryCheck.h" />
|
||||
<ClInclude Include="utils\StringHelper.h" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<ImportGroup Label="ExtensionTargets">
|
||||
</ImportGroup>
|
||||
</Project>
|
||||
171
include/INIH/INIReader.cpp
Normal file
171
include/INIH/INIReader.cpp
Normal file
@ -0,0 +1,171 @@
|
||||
// Read an INI file into easy-to-access name/value pairs.
|
||||
|
||||
// SPDX-License-Identifier: BSD-3-Clause
|
||||
|
||||
// Copyright (C) 2009-2020, Ben Hoyt
|
||||
|
||||
// inih and INIReader are released under the New BSD license (see LICENSE.txt).
|
||||
// Go to the project home page for more info:
|
||||
//
|
||||
// https://github.com/benhoyt/inih
|
||||
|
||||
#include <algorithm>
|
||||
#include <cctype>
|
||||
#include <cstdlib>
|
||||
#include "ini.h"
|
||||
#include "INIReader.h"
|
||||
|
||||
using std::string;
|
||||
|
||||
INIReader::INIReader(const string& filename)
|
||||
{
|
||||
_error = ini_parse(filename.c_str(), ValueHandler, this);
|
||||
}
|
||||
|
||||
INIReader::INIReader(const char *buffer, size_t buffer_size)
|
||||
{
|
||||
_error = ini_parse_string_length(buffer, buffer_size, ValueHandler, this);
|
||||
}
|
||||
|
||||
int INIReader::ParseError() const
|
||||
{
|
||||
return _error;
|
||||
}
|
||||
|
||||
string INIReader::Get(const string& section, const string& name, const string& default_value) const
|
||||
{
|
||||
string key = MakeKey(section, name);
|
||||
// Use _values.find() here instead of _values.at() to support pre C++11 compilers
|
||||
return _values.count(key) ? _values.find(key)->second : default_value;
|
||||
}
|
||||
|
||||
string INIReader::GetString(const string& section, const string& name, const string& default_value) const
|
||||
{
|
||||
const string str = Get(section, name, "");
|
||||
return str.empty() ? default_value : str;
|
||||
}
|
||||
|
||||
long INIReader::GetInteger(const string& section, const string& name, long default_value) const
|
||||
{
|
||||
string valstr = Get(section, name, "");
|
||||
const char* value = valstr.c_str();
|
||||
char* end;
|
||||
// This parses "1234" (decimal) and also "0x4D2" (hex)
|
||||
long n = strtol(value, &end, 0);
|
||||
return end > value ? n : default_value;
|
||||
}
|
||||
|
||||
INI_API int64_t INIReader::GetInteger64(const string& section, const string& name, int64_t default_value) const
|
||||
{
|
||||
string valstr = Get(section, name, "");
|
||||
const char* value = valstr.c_str();
|
||||
char* end;
|
||||
// This parses "1234" (decimal) and also "0x4D2" (hex)
|
||||
int64_t n = strtoll(value, &end, 0);
|
||||
return end > value ? n : default_value;
|
||||
}
|
||||
|
||||
unsigned long INIReader::GetUnsigned(const string& section, const string& name, unsigned long default_value) const
|
||||
{
|
||||
string valstr = Get(section, name, "");
|
||||
const char* value = valstr.c_str();
|
||||
char* end;
|
||||
// This parses "1234" (decimal) and also "0x4D2" (hex)
|
||||
unsigned long n = strtoul(value, &end, 0);
|
||||
return end > value ? n : default_value;
|
||||
}
|
||||
|
||||
INI_API uint64_t INIReader::GetUnsigned64(const string& section, const string& name, uint64_t default_value) const
|
||||
{
|
||||
string valstr = Get(section, name, "");
|
||||
const char* value = valstr.c_str();
|
||||
char* end;
|
||||
// This parses "1234" (decimal) and also "0x4D2" (hex)
|
||||
uint64_t n = strtoull(value, &end, 0);
|
||||
return end > value ? n : default_value;
|
||||
}
|
||||
|
||||
double INIReader::GetReal(const string& section, const string& name, double default_value) const
|
||||
{
|
||||
string valstr = Get(section, name, "");
|
||||
const char* value = valstr.c_str();
|
||||
char* end;
|
||||
double n = strtod(value, &end);
|
||||
return end > value ? n : default_value;
|
||||
}
|
||||
|
||||
bool INIReader::GetBoolean(const string& section, const string& name, bool default_value) const
|
||||
{
|
||||
string valstr = Get(section, name, "");
|
||||
// Convert to lower case to make string comparisons case-insensitive
|
||||
std::transform(valstr.begin(), valstr.end(), valstr.begin(),
|
||||
[](const unsigned char& ch) { return static_cast<unsigned char>(::tolower(ch)); });
|
||||
if (valstr == "true" || valstr == "yes" || valstr == "on" || valstr == "1")
|
||||
return true;
|
||||
else if (valstr == "false" || valstr == "no" || valstr == "off" || valstr == "0")
|
||||
return false;
|
||||
else
|
||||
return default_value;
|
||||
}
|
||||
|
||||
std::vector<string> INIReader::Sections() const
|
||||
{
|
||||
std::set<string> sectionSet;
|
||||
for (std::map<string, string>::const_iterator it = _values.begin(); it != _values.end(); ++it) {
|
||||
size_t pos = it->first.find('=');
|
||||
if (pos != string::npos) {
|
||||
sectionSet.insert(it->first.substr(0, pos));
|
||||
}
|
||||
}
|
||||
return std::vector<string>(sectionSet.begin(), sectionSet.end());
|
||||
}
|
||||
|
||||
std::vector<string> INIReader::Keys(const string& section) const
|
||||
{
|
||||
std::vector<string> keys;
|
||||
string keyPrefix = MakeKey(section, "");
|
||||
for (std::map<string, string>::const_iterator it = _values.begin(); it != _values.end(); ++it) {
|
||||
if (it->first.compare(0, keyPrefix.length(), keyPrefix) == 0) {
|
||||
keys.push_back(it->first.substr(keyPrefix.length()));
|
||||
}
|
||||
}
|
||||
return keys;
|
||||
}
|
||||
|
||||
bool INIReader::HasSection(const string& section) const
|
||||
{
|
||||
const string key = MakeKey(section, "");
|
||||
std::map<string, string>::const_iterator pos = _values.lower_bound(key);
|
||||
if (pos == _values.end())
|
||||
return false;
|
||||
// Does the key at the lower_bound pos start with "section"?
|
||||
return pos->first.compare(0, key.length(), key) == 0;
|
||||
}
|
||||
|
||||
bool INIReader::HasValue(const string& section, const string& name) const
|
||||
{
|
||||
string key = MakeKey(section, name);
|
||||
return _values.count(key);
|
||||
}
|
||||
|
||||
string INIReader::MakeKey(const string& section, const string& name)
|
||||
{
|
||||
string key = section + "=" + name;
|
||||
// Convert to lower case to make section/name lookups case-insensitive
|
||||
std::transform(key.begin(), key.end(), key.begin(),
|
||||
[](const unsigned char& ch) { return static_cast<unsigned char>(::tolower(ch)); });
|
||||
return key;
|
||||
}
|
||||
|
||||
int INIReader::ValueHandler(void* user, const char* section, const char* name,
|
||||
const char* value)
|
||||
{
|
||||
if (!name) // Happens when INI_CALL_HANDLER_ON_NEW_SECTION enabled
|
||||
return 1;
|
||||
INIReader* reader = static_cast<INIReader*>(user);
|
||||
string key = MakeKey(section, name);
|
||||
if (reader->_values[key].size() > 0)
|
||||
reader->_values[key] += "\n";
|
||||
reader->_values[key] += value ? value : "";
|
||||
return 1;
|
||||
}
|
||||
115
include/INIH/INIReader.h
Normal file
115
include/INIH/INIReader.h
Normal file
@ -0,0 +1,115 @@
|
||||
// Read an INI file into easy-to-access name/value pairs.
|
||||
|
||||
// SPDX-License-Identifier: BSD-3-Clause
|
||||
|
||||
// Copyright (C) 2009-2020, Ben Hoyt
|
||||
|
||||
// inih and INIReader are released under the New BSD license (see LICENSE.txt).
|
||||
// Go to the project home page for more info:
|
||||
//
|
||||
// https://github.com/benhoyt/inih
|
||||
|
||||
#ifndef INIREADER_H
|
||||
#define INIREADER_H
|
||||
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include <cstdint>
|
||||
#include <vector>
|
||||
#include <set>
|
||||
|
||||
// Visibility symbols, required for Windows DLLs
|
||||
#ifndef INI_API
|
||||
#if defined _WIN32 || defined __CYGWIN__
|
||||
# ifdef INI_SHARED_LIB
|
||||
# ifdef INI_SHARED_LIB_BUILDING
|
||||
# define INI_API __declspec(dllexport)
|
||||
# else
|
||||
# define INI_API __declspec(dllimport)
|
||||
# endif
|
||||
# else
|
||||
# define INI_API
|
||||
# endif
|
||||
#else
|
||||
# if defined(__GNUC__) && __GNUC__ >= 4
|
||||
# define INI_API __attribute__ ((visibility ("default")))
|
||||
# else
|
||||
# define INI_API
|
||||
# endif
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// Read an INI file into easy-to-access name/value pairs. (Note that I've gone
|
||||
// for simplicity here rather than speed, but it should be pretty decent.)
|
||||
class INIReader
|
||||
{
|
||||
public:
|
||||
// Construct INIReader and parse given filename. See ini.h for more info
|
||||
// about the parsing.
|
||||
INI_API explicit INIReader(const std::string& filename);
|
||||
|
||||
// Construct INIReader and parse given buffer. See ini.h for more info
|
||||
// about the parsing.
|
||||
INI_API explicit INIReader(const char *buffer, size_t buffer_size);
|
||||
|
||||
// Return the result of ini_parse(), i.e., 0 on success, line number of
|
||||
// first error on parse error, or -1 on file open error.
|
||||
INI_API int ParseError() const;
|
||||
|
||||
// Get a string value from INI file, returning default_value if not found.
|
||||
INI_API std::string Get(const std::string& section, const std::string& name,
|
||||
const std::string& default_value) const;
|
||||
|
||||
// Get a string value from INI file, returning default_value if not found,
|
||||
// empty, or contains only whitespace.
|
||||
INI_API std::string GetString(const std::string& section, const std::string& name,
|
||||
const std::string& default_value) const;
|
||||
|
||||
// Get an integer (long) value from INI file, returning default_value if
|
||||
// not found or not a valid integer (decimal "1234", "-1234", or hex "0x4d2").
|
||||
INI_API long GetInteger(const std::string& section, const std::string& name, long default_value) const;
|
||||
|
||||
// Get a 64-bit integer (int64_t) value from INI file, returning default_value if
|
||||
// not found or not a valid integer (decimal "1234", "-1234", or hex "0x4d2").
|
||||
INI_API int64_t GetInteger64(const std::string& section, const std::string& name, int64_t default_value) const;
|
||||
|
||||
// Get an unsigned integer (unsigned long) value from INI file, returning default_value if
|
||||
// not found or not a valid unsigned integer (decimal "1234", or hex "0x4d2").
|
||||
INI_API unsigned long GetUnsigned(const std::string& section, const std::string& name, unsigned long default_value) const;
|
||||
|
||||
// Get an unsigned 64-bit integer (uint64_t) value from INI file, returning default_value if
|
||||
// not found or not a valid unsigned integer (decimal "1234", or hex "0x4d2").
|
||||
INI_API uint64_t GetUnsigned64(const std::string& section, const std::string& name, uint64_t default_value) const;
|
||||
|
||||
// Get a real (floating point double) value from INI file, returning
|
||||
// default_value if not found or not a valid floating point value
|
||||
// according to strtod().
|
||||
INI_API double GetReal(const std::string& section, const std::string& name, double default_value) const;
|
||||
|
||||
// Get a boolean value from INI file, returning default_value if not found or if
|
||||
// not a valid true/false value. Valid true values are "true", "yes", "on", "1",
|
||||
// and valid false values are "false", "no", "off", "0" (not case sensitive).
|
||||
INI_API bool GetBoolean(const std::string& section, const std::string& name, bool default_value) const;
|
||||
|
||||
// Return a newly-allocated vector of all section names, in alphabetical order.
|
||||
INI_API std::vector<std::string> Sections() const;
|
||||
|
||||
// Return a newly-allocated vector of keys in the given section, in alphabetical order.
|
||||
INI_API std::vector<std::string> Keys(const std::string& section) const;
|
||||
|
||||
// Return true if the given section exists (section must contain at least
|
||||
// one name=value pair).
|
||||
INI_API bool HasSection(const std::string& section) const;
|
||||
|
||||
// Return true if a value exists with the given section and field names.
|
||||
INI_API bool HasValue(const std::string& section, const std::string& name) const;
|
||||
|
||||
protected:
|
||||
int _error;
|
||||
std::map<std::string, std::string> _values;
|
||||
static std::string MakeKey(const std::string& section, const std::string& name);
|
||||
static int ValueHandler(void* user, const char* section, const char* name,
|
||||
const char* value);
|
||||
};
|
||||
|
||||
#endif // INIREADER_H
|
||||
27
include/INIH/LICENSE.txt
Normal file
27
include/INIH/LICENSE.txt
Normal file
@ -0,0 +1,27 @@
|
||||
|
||||
The "inih" library is distributed under the New BSD license:
|
||||
|
||||
Copyright (c) 2009, Ben Hoyt
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of Ben Hoyt nor the names of its contributors
|
||||
may be used to endorse or promote products derived from this software
|
||||
without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY BEN HOYT ''AS IS'' AND ANY
|
||||
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL BEN HOYT BE LIABLE FOR ANY
|
||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
175
include/INIH/README.md
Normal file
175
include/INIH/README.md
Normal file
@ -0,0 +1,175 @@
|
||||
# inih (INI Not Invented Here)
|
||||
|
||||
[](https://github.com/benhoyt/inih/actions/workflows/tests.yml)
|
||||
|
||||
**inih (INI Not Invented Here)** is a simple [.INI file](http://en.wikipedia.org/wiki/INI_file) parser written in C. It's only a couple of pages of code, and it was designed to be _small and simple_, so it's good for embedded systems. It's also more or less compatible with Python's [ConfigParser](http://docs.python.org/library/configparser.html) style of .INI files, including RFC 822-style multi-line syntax and `name: value` entries.
|
||||
|
||||
To use it, just give `ini_parse()` an INI file, and it will call a callback for every `name=value` pair parsed, giving you strings for the section, name, and value. It's done this way ("SAX style") because it works well on low-memory embedded systems, but also because it makes for a KISS implementation.
|
||||
|
||||
You can also call `ini_parse_file()` to parse directly from a `FILE*` object, `ini_parse_string()` to parse data from a string, or `ini_parse_stream()` to parse using a custom fgets-style reader function for custom I/O.
|
||||
|
||||
Download a release, browse the source, or read about [how to use inih in a DRY style](http://blog.brush.co.nz/2009/08/xmacros/) with X-Macros.
|
||||
|
||||
|
||||
## Compile-time options ##
|
||||
|
||||
You can control various aspects of inih using preprocessor defines:
|
||||
|
||||
### Syntax options ###
|
||||
|
||||
* **Multi-line entries:** By default, inih supports multi-line entries in the style of Python's ConfigParser. To disable, add `-DINI_ALLOW_MULTILINE=0`.
|
||||
* **UTF-8 BOM:** By default, inih allows a UTF-8 BOM sequence (0xEF 0xBB 0xBF) at the start of INI files. To disable, add `-DINI_ALLOW_BOM=0`.
|
||||
* **Inline comments:** By default, inih allows inline comments with the `;` character. To disable, add `-DINI_ALLOW_INLINE_COMMENTS=0`. You can also specify which character(s) start an inline comment using `INI_INLINE_COMMENT_PREFIXES`.
|
||||
* **Start-of-line comments:** By default, inih allows both `;` and `#` to start a comment at the beginning of a line. You can override this by changing `INI_START_COMMENT_PREFIXES`.
|
||||
* **Allow no value:** By default, inih treats a name with no value (no `=` or `:` on the line) as an error. To allow names with no values, add `-DINI_ALLOW_NO_VALUE=1`, and inih will call your handler function with value set to NULL.
|
||||
|
||||
### Parsing options ###
|
||||
|
||||
* **Stop on first error:** By default, inih keeps parsing the rest of the file after an error. To stop parsing on the first error, add `-DINI_STOP_ON_FIRST_ERROR=1`.
|
||||
* **Report line numbers:** By default, the `ini_handler` callback doesn't receive the line number as a parameter. If you need that, add `-DINI_HANDLER_LINENO=1`.
|
||||
* **Call handler on new section:** By default, inih only calls the handler on each `name=value` pair. To detect new sections (e.g., the INI file has multiple sections with the same name), add `-DINI_CALL_HANDLER_ON_NEW_SECTION=1`. Your handler function will then be called each time a new section is encountered, with `section` set to the new section name but `name` and `value` set to NULL.
|
||||
|
||||
### Memory options ###
|
||||
|
||||
* **Stack vs heap:** By default, inih creates a fixed-sized line buffer on the stack. To allocate on the heap using `malloc` instead, specify `-DINI_USE_STACK=0`.
|
||||
* **Maximum line length:** The default maximum line length (for stack or heap) is 200 bytes. To override this, add something like `-DINI_MAX_LINE=1000`. Note that `INI_MAX_LINE` must be 3 more than the longest line (due to `\r`, `\n`, and the NUL).
|
||||
* **Initial malloc size:** `INI_INITIAL_ALLOC` specifies the initial malloc size when using the heap. It defaults to 200 bytes.
|
||||
* **Allow realloc:** By default when using the heap (`-DINI_USE_STACK=0`), inih allocates a fixed-sized buffer of `INI_INITIAL_ALLOC` bytes. To allow this to grow to `INI_MAX_LINE` bytes, doubling if needed, set `-DINI_ALLOW_REALLOC=1`.
|
||||
* **Custom allocator:** By default when using the heap, the standard library's `malloc`, `free`, and `realloc` functions are used; to use a custom allocator, specify `-DINI_CUSTOM_ALLOCATOR=1` (and `-DINI_USE_STACK=0`). You must define and link functions named `ini_malloc`, `ini_free`, and (if `INI_ALLOW_REALLOC` is set) `ini_realloc`, which must have the same signatures as the `stdlib.h` memory allocation functions.
|
||||
|
||||
## Simple example in C ##
|
||||
|
||||
```c
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "../ini.h"
|
||||
|
||||
typedef struct
|
||||
{
|
||||
int version;
|
||||
const char* name;
|
||||
const char* email;
|
||||
} configuration;
|
||||
|
||||
static int handler(void* user, const char* section, const char* name,
|
||||
const char* value)
|
||||
{
|
||||
configuration* pconfig = (configuration*)user;
|
||||
|
||||
#define MATCH(s, n) strcmp(section, s) == 0 && strcmp(name, n) == 0
|
||||
if (MATCH("protocol", "version")) {
|
||||
pconfig->version = atoi(value);
|
||||
} else if (MATCH("user", "name")) {
|
||||
pconfig->name = strdup(value);
|
||||
} else if (MATCH("user", "email")) {
|
||||
pconfig->email = strdup(value);
|
||||
} else {
|
||||
return 0; /* unknown section/name, error */
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
int main(int argc, char* argv[])
|
||||
{
|
||||
configuration config;
|
||||
|
||||
if (ini_parse("test.ini", handler, &config) < 0) {
|
||||
printf("Can't load 'test.ini'\n");
|
||||
return 1;
|
||||
}
|
||||
printf("Config loaded from 'test.ini': version=%d, name=%s, email=%s\n",
|
||||
config.version, config.name, config.email);
|
||||
return 0;
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
## C++ example ##
|
||||
|
||||
If you're into C++ and the STL, there is also an easy-to-use [INIReader class](https://github.com/benhoyt/inih/blob/master/cpp/INIReader.h) that stores values in a `map` and lets you `Get()` them:
|
||||
|
||||
```cpp
|
||||
#include <iostream>
|
||||
#include "INIReader.h"
|
||||
|
||||
int main()
|
||||
{
|
||||
INIReader reader("../examples/test.ini");
|
||||
|
||||
if (reader.ParseError() < 0) {
|
||||
std::cout << "Can't load 'test.ini'\n";
|
||||
return 1;
|
||||
}
|
||||
std::cout << "Config loaded from 'test.ini': version="
|
||||
<< reader.GetInteger("protocol", "version", -1) << ", name="
|
||||
<< reader.Get("user", "name", "UNKNOWN") << ", email="
|
||||
<< reader.Get("user", "email", "UNKNOWN") << ", pi="
|
||||
<< reader.GetReal("user", "pi", -1) << ", active="
|
||||
<< reader.GetBoolean("user", "active", true) << "\n";
|
||||
return 0;
|
||||
}
|
||||
```
|
||||
|
||||
This simple C++ API works fine, but it's not very fully-fledged. I'm not planning to work more on the C++ API at the moment, so if you want a bit more power (for example `GetSections()` and `GetFields()` functions), see these forks:
|
||||
|
||||
* https://github.com/Blandinium/inih
|
||||
* https://github.com/OSSystems/inih
|
||||
|
||||
|
||||
## Differences from ConfigParser ##
|
||||
|
||||
Some differences between inih and Python's [ConfigParser](http://docs.python.org/library/configparser.html) standard library module:
|
||||
|
||||
* INI name=value pairs given above any section headers are treated as valid items with no section (section name is an empty string). In ConfigParser having no section is an error.
|
||||
* Line continuations are handled with leading whitespace on continued lines (like ConfigParser). However, instead of concatenating continued lines together, they are treated as separate values for the same key (unlike ConfigParser).
|
||||
|
||||
|
||||
## Platform-specific notes ##
|
||||
|
||||
* Windows/Win32 uses UTF-16 filenames natively, so to handle Unicode paths you need to call `_wfopen()` to open a file and then `ini_parse_file()` to parse it; inih does not include `wchar_t` or Unicode handling.
|
||||
|
||||
## Meson notes ##
|
||||
|
||||
* The `meson.build` file is not required to use or compile inih, its main purpose is for distributions.
|
||||
* By default Meson is set up for distro installation, but this behavior can be configured for embedded use cases:
|
||||
* with `-Ddefault_library=static` static libraries are built.
|
||||
* with `-Ddistro_install=false` libraries, headers and pkg-config files won't be installed.
|
||||
* with `-Dwith_INIReader=false` you can disable building the C++ library.
|
||||
* All compile-time options are implemented in Meson as well, you can take a look at [meson_options.txt](https://github.com/benhoyt/inih/blob/master/meson_options.txt) for their definition. These won't work if `distro_install` is set to `true`.
|
||||
* If you want to use inih for programs which may be shipped in a distro, consider linking against the shared libraries. The pkg-config entries are `inih` and `INIReader`.
|
||||
* In case you use inih as a Meson subproject, you can use the `inih_dep` and `INIReader_dep` dependency variables. You might want to set `default_library=static` and `distro_install=false` for the subproject. An official Wrap is provided on [WrapDB](https://wrapdb.mesonbuild.com/inih).
|
||||
* For packagers: if you want to tag the version in the pkg-config file, you will need to do this downstream. Add `version : '<version_as_int>',` after the `license` tag in the `project()` function and `version : meson.project_version(),` after the `soversion` tag in both `library()` functions.
|
||||
|
||||
## Using inih with tipi.build
|
||||
|
||||
`inih` can be easily used in [tipi.build](https://tipi.build) projects simply by adding the following entry to your `.tipi/deps` (replace `r56` with the latest version tag):
|
||||
|
||||
```json
|
||||
{
|
||||
"benhoyt/inih": { "@": "r56" }
|
||||
}
|
||||
```
|
||||
|
||||
The required include path in your project is:
|
||||
|
||||
```c
|
||||
#include <ini.h>
|
||||
```
|
||||
|
||||
## Building from vcpkg ##
|
||||
|
||||
You can build and install inih using [vcpkg](https://github.com/microsoft/vcpkg/) dependency manager:
|
||||
|
||||
git clone https://github.com/Microsoft/vcpkg.git
|
||||
cd vcpkg
|
||||
./bootstrap-vcpkg.sh
|
||||
./vcpkg integrate install
|
||||
./vcpkg install inih
|
||||
|
||||
The inih port in vcpkg is kept up to date by microsoft team members and community contributors.
|
||||
If the version is out of date, please [create an issue or pull request](https://github.com/Microsoft/vcpkg) on the vcpkg repository.
|
||||
|
||||
## Related links ##
|
||||
|
||||
* [Conan package for inih](https://github.com/mohamedghita/conan-inih) (Conan is a C/C++ package manager)
|
||||
327
include/INIH/ini.c
Normal file
327
include/INIH/ini.c
Normal file
@ -0,0 +1,327 @@
|
||||
/* inih -- simple .INI file parser
|
||||
|
||||
SPDX-License-Identifier: BSD-3-Clause
|
||||
|
||||
Copyright (C) 2009-2020, Ben Hoyt
|
||||
|
||||
inih is released under the New BSD license (see LICENSE.txt). Go to the project
|
||||
home page for more info:
|
||||
|
||||
https://github.com/benhoyt/inih
|
||||
|
||||
*/
|
||||
|
||||
#if defined(_MSC_VER) && !defined(_CRT_SECURE_NO_WARNINGS)
|
||||
#define _CRT_SECURE_NO_WARNINGS
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#include <ctype.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "ini.h"
|
||||
|
||||
#if !INI_USE_STACK
|
||||
#if INI_CUSTOM_ALLOCATOR
|
||||
#include <stddef.h>
|
||||
void* ini_malloc(size_t size);
|
||||
void ini_free(void* ptr);
|
||||
void* ini_realloc(void* ptr, size_t size);
|
||||
#else
|
||||
#include <stdlib.h>
|
||||
#define ini_malloc malloc
|
||||
#define ini_free free
|
||||
#define ini_realloc realloc
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#define MAX_SECTION 50
|
||||
#define MAX_NAME 50
|
||||
|
||||
/* Used by ini_parse_string() to keep track of string parsing state. */
|
||||
typedef struct {
|
||||
const char* ptr;
|
||||
size_t num_left;
|
||||
} ini_parse_string_ctx;
|
||||
|
||||
/* Strip whitespace chars off end of given string, in place. end must be a
|
||||
pointer to the NUL terminator at the end of the string. Return s. */
|
||||
static char* ini_rstrip(char* s, char* end)
|
||||
{
|
||||
while (end > s && isspace((unsigned char)(*--end)))
|
||||
*end = '\0';
|
||||
return s;
|
||||
}
|
||||
|
||||
/* Return pointer to first non-whitespace char in given string. */
|
||||
static char* ini_lskip(const char* s)
|
||||
{
|
||||
while (*s && isspace((unsigned char)(*s)))
|
||||
s++;
|
||||
return (char*)s;
|
||||
}
|
||||
|
||||
/* Return pointer to first char (of chars) or inline comment in given string,
|
||||
or pointer to NUL at end of string if neither found. Inline comment must
|
||||
be prefixed by a whitespace character to register as a comment. */
|
||||
static char* ini_find_chars_or_comment(const char* s, const char* chars)
|
||||
{
|
||||
#if INI_ALLOW_INLINE_COMMENTS
|
||||
int was_space = 0;
|
||||
while (*s && (!chars || !strchr(chars, *s)) &&
|
||||
!(was_space && strchr(INI_INLINE_COMMENT_PREFIXES, *s))) {
|
||||
was_space = isspace((unsigned char)(*s));
|
||||
s++;
|
||||
}
|
||||
#else
|
||||
while (*s && (!chars || !strchr(chars, *s))) {
|
||||
s++;
|
||||
}
|
||||
#endif
|
||||
return (char*)s;
|
||||
}
|
||||
|
||||
/* Similar to strncpy, but ensures dest (size bytes) is
|
||||
NUL-terminated, and doesn't pad with NULs. */
|
||||
static char* ini_strncpy0(char* dest, const char* src, size_t size)
|
||||
{
|
||||
/* Could use strncpy internally, but it causes gcc warnings (see issue #91) */
|
||||
size_t i;
|
||||
for (i = 0; i < size - 1 && src[i]; i++)
|
||||
dest[i] = src[i];
|
||||
dest[i] = '\0';
|
||||
return dest;
|
||||
}
|
||||
|
||||
/* See documentation in header file. */
|
||||
int ini_parse_stream(ini_reader reader, void* stream, ini_handler handler,
|
||||
void* user)
|
||||
{
|
||||
/* Uses a fair bit of stack (use heap instead if you need to) */
|
||||
#if INI_USE_STACK
|
||||
char line[INI_MAX_LINE];
|
||||
size_t max_line = INI_MAX_LINE;
|
||||
#else
|
||||
char* line;
|
||||
size_t max_line = INI_INITIAL_ALLOC;
|
||||
#endif
|
||||
#if INI_ALLOW_REALLOC && !INI_USE_STACK
|
||||
char* new_line;
|
||||
#endif
|
||||
char section[MAX_SECTION] = "";
|
||||
#if INI_ALLOW_MULTILINE
|
||||
char prev_name[MAX_NAME] = "";
|
||||
#endif
|
||||
|
||||
size_t offset;
|
||||
char* start;
|
||||
char* end;
|
||||
char* name;
|
||||
char* value;
|
||||
int lineno = 0;
|
||||
int error = 0;
|
||||
char abyss[16]; /* Used to consume input when a line is too long. */
|
||||
|
||||
#if !INI_USE_STACK
|
||||
line = (char*)ini_malloc(INI_INITIAL_ALLOC);
|
||||
if (!line) {
|
||||
return -2;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if INI_HANDLER_LINENO
|
||||
#define HANDLER(u, s, n, v) handler(u, s, n, v, lineno)
|
||||
#else
|
||||
#define HANDLER(u, s, n, v) handler(u, s, n, v)
|
||||
#endif
|
||||
|
||||
/* Scan through stream line by line */
|
||||
while (reader(line, (int)max_line, stream) != NULL) {
|
||||
offset = strlen(line);
|
||||
|
||||
#if INI_ALLOW_REALLOC && !INI_USE_STACK
|
||||
while (offset == max_line - 1 && line[offset - 1] != '\n') {
|
||||
max_line *= 2;
|
||||
if (max_line > INI_MAX_LINE)
|
||||
max_line = INI_MAX_LINE;
|
||||
new_line = ini_realloc(line, max_line);
|
||||
if (!new_line) {
|
||||
ini_free(line);
|
||||
return -2;
|
||||
}
|
||||
line = new_line;
|
||||
if (reader(line + offset, (int)(max_line - offset), stream) == NULL)
|
||||
break;
|
||||
offset += strlen(line + offset);
|
||||
if (max_line >= INI_MAX_LINE)
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
|
||||
lineno++;
|
||||
|
||||
/* If line exceeded INI_MAX_LINE bytes, discard till end of line. */
|
||||
if (offset == max_line - 1 && line[offset - 1] != '\n') {
|
||||
while (reader(abyss, sizeof(abyss), stream) != NULL) {
|
||||
if (!error)
|
||||
error = lineno;
|
||||
if (abyss[strlen(abyss) - 1] == '\n')
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
start = line;
|
||||
#if INI_ALLOW_BOM
|
||||
if (lineno == 1 && (unsigned char)start[0] == 0xEF &&
|
||||
(unsigned char)start[1] == 0xBB &&
|
||||
(unsigned char)start[2] == 0xBF) {
|
||||
start += 3;
|
||||
}
|
||||
#endif
|
||||
start = ini_rstrip(ini_lskip(start), line + offset);
|
||||
|
||||
if (strchr(INI_START_COMMENT_PREFIXES, *start)) {
|
||||
/* Start-of-line comment */
|
||||
}
|
||||
#if INI_ALLOW_MULTILINE
|
||||
else if (*prev_name && *start && start > line) {
|
||||
#if INI_ALLOW_INLINE_COMMENTS
|
||||
end = ini_find_chars_or_comment(start, NULL);
|
||||
*end = '\0';
|
||||
ini_rstrip(start, end);
|
||||
#endif
|
||||
/* Non-blank line with leading whitespace, treat as continuation
|
||||
of previous name's value (as per Python configparser). */
|
||||
if (!HANDLER(user, section, prev_name, start) && !error)
|
||||
error = lineno;
|
||||
}
|
||||
#endif
|
||||
else if (*start == '[') {
|
||||
/* A "[section]" line */
|
||||
end = ini_find_chars_or_comment(start + 1, "]");
|
||||
if (*end == ']') {
|
||||
*end = '\0';
|
||||
ini_strncpy0(section, start + 1, sizeof(section));
|
||||
#if INI_ALLOW_MULTILINE
|
||||
*prev_name = '\0';
|
||||
#endif
|
||||
#if INI_CALL_HANDLER_ON_NEW_SECTION
|
||||
if (!HANDLER(user, section, NULL, NULL) && !error)
|
||||
error = lineno;
|
||||
#endif
|
||||
}
|
||||
else if (!error) {
|
||||
/* No ']' found on section line */
|
||||
error = lineno;
|
||||
}
|
||||
}
|
||||
else if (*start) {
|
||||
/* Not a comment, must be a name[=:]value pair */
|
||||
end = ini_find_chars_or_comment(start, "=:");
|
||||
if (*end == '=' || *end == ':') {
|
||||
*end = '\0';
|
||||
name = ini_rstrip(start, end);
|
||||
value = end + 1;
|
||||
#if INI_ALLOW_INLINE_COMMENTS
|
||||
end = ini_find_chars_or_comment(value, NULL);
|
||||
*end = '\0';
|
||||
#endif
|
||||
value = ini_lskip(value);
|
||||
ini_rstrip(value, end);
|
||||
|
||||
#if INI_ALLOW_MULTILINE
|
||||
ini_strncpy0(prev_name, name, sizeof(prev_name));
|
||||
#endif
|
||||
/* Valid name[=:]value pair found, call handler */
|
||||
if (!HANDLER(user, section, name, value) && !error)
|
||||
error = lineno;
|
||||
}
|
||||
else {
|
||||
/* No '=' or ':' found on name[=:]value line */
|
||||
#if INI_ALLOW_NO_VALUE
|
||||
*end = '\0';
|
||||
name = ini_rstrip(start, end);
|
||||
if (!HANDLER(user, section, name, NULL) && !error)
|
||||
error = lineno;
|
||||
#else
|
||||
if (!error)
|
||||
error = lineno;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
#if INI_STOP_ON_FIRST_ERROR
|
||||
if (error)
|
||||
break;
|
||||
#endif
|
||||
}
|
||||
|
||||
#if !INI_USE_STACK
|
||||
ini_free(line);
|
||||
#endif
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
/* See documentation in header file. */
|
||||
int ini_parse_file(FILE* file, ini_handler handler, void* user)
|
||||
{
|
||||
return ini_parse_stream((ini_reader)fgets, file, handler, user);
|
||||
}
|
||||
|
||||
/* See documentation in header file. */
|
||||
int ini_parse(const char* filename, ini_handler handler, void* user)
|
||||
{
|
||||
FILE* file;
|
||||
int error;
|
||||
|
||||
file = fopen(filename, "r");
|
||||
if (!file)
|
||||
return -1;
|
||||
error = ini_parse_file(file, handler, user);
|
||||
fclose(file);
|
||||
return error;
|
||||
}
|
||||
|
||||
/* An ini_reader function to read the next line from a string buffer. This
|
||||
is the fgets() equivalent used by ini_parse_string(). */
|
||||
static char* ini_reader_string(char* str, int num, void* stream) {
|
||||
ini_parse_string_ctx* ctx = (ini_parse_string_ctx*)stream;
|
||||
const char* ctx_ptr = ctx->ptr;
|
||||
size_t ctx_num_left = ctx->num_left;
|
||||
char* strp = str;
|
||||
char c;
|
||||
|
||||
if (ctx_num_left == 0 || num < 2)
|
||||
return NULL;
|
||||
|
||||
while (num > 1 && ctx_num_left != 0) {
|
||||
c = *ctx_ptr++;
|
||||
ctx_num_left--;
|
||||
*strp++ = c;
|
||||
if (c == '\n')
|
||||
break;
|
||||
num--;
|
||||
}
|
||||
|
||||
*strp = '\0';
|
||||
ctx->ptr = ctx_ptr;
|
||||
ctx->num_left = ctx_num_left;
|
||||
return str;
|
||||
}
|
||||
|
||||
/* See documentation in header file. */
|
||||
int ini_parse_string(const char* string, ini_handler handler, void* user) {
|
||||
return ini_parse_string_length(string, strlen(string), handler, user);
|
||||
}
|
||||
|
||||
/* See documentation in header file. */
|
||||
int ini_parse_string_length(const char* string, size_t length,
|
||||
ini_handler handler, void* user) {
|
||||
ini_parse_string_ctx ctx;
|
||||
|
||||
ctx.ptr = string;
|
||||
ctx.num_left = length;
|
||||
return ini_parse_stream((ini_reader)ini_reader_string, &ctx, handler,
|
||||
user);
|
||||
}
|
||||
189
include/INIH/ini.h
Normal file
189
include/INIH/ini.h
Normal file
@ -0,0 +1,189 @@
|
||||
/* inih -- simple .INI file parser
|
||||
|
||||
SPDX-License-Identifier: BSD-3-Clause
|
||||
|
||||
Copyright (C) 2009-2020, Ben Hoyt
|
||||
|
||||
inih is released under the New BSD license (see LICENSE.txt). Go to the project
|
||||
home page for more info:
|
||||
|
||||
https://github.com/benhoyt/inih
|
||||
|
||||
*/
|
||||
|
||||
#ifndef INI_H
|
||||
#define INI_H
|
||||
|
||||
/* Make this header file easier to include in C++ code */
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
/* Nonzero if ini_handler callback should accept lineno parameter. */
|
||||
#ifndef INI_HANDLER_LINENO
|
||||
#define INI_HANDLER_LINENO 0
|
||||
#endif
|
||||
|
||||
/* Visibility symbols, required for Windows DLLs */
|
||||
#ifndef INI_API
|
||||
#if defined _WIN32 || defined __CYGWIN__
|
||||
# ifdef INI_SHARED_LIB
|
||||
# ifdef INI_SHARED_LIB_BUILDING
|
||||
# define INI_API __declspec(dllexport)
|
||||
# else
|
||||
# define INI_API __declspec(dllimport)
|
||||
# endif
|
||||
# else
|
||||
# define INI_API
|
||||
# endif
|
||||
#else
|
||||
# if defined(__GNUC__) && __GNUC__ >= 4
|
||||
# define INI_API __attribute__ ((visibility ("default")))
|
||||
# else
|
||||
# define INI_API
|
||||
# endif
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* Typedef for prototype of handler function.
|
||||
|
||||
Note that even though the value parameter has type "const char*", the user
|
||||
may cast to "char*" and modify its content, as the value is not used again
|
||||
after the call to ini_handler. This is not true of section and name --
|
||||
those must not be modified.
|
||||
*/
|
||||
#if INI_HANDLER_LINENO
|
||||
typedef int (*ini_handler)(void* user, const char* section,
|
||||
const char* name, const char* value,
|
||||
int lineno);
|
||||
#else
|
||||
typedef int (*ini_handler)(void* user, const char* section,
|
||||
const char* name, const char* value);
|
||||
#endif
|
||||
|
||||
/* Typedef for prototype of fgets-style reader function. */
|
||||
typedef char* (*ini_reader)(char* str, int num, void* stream);
|
||||
|
||||
/* Parse given INI-style file. May have [section]s, name=value pairs
|
||||
(whitespace stripped), and comments starting with ';' (semicolon). Section
|
||||
is "" if name=value pair parsed before any section heading. name:value
|
||||
pairs are also supported as a concession to Python's configparser.
|
||||
|
||||
For each name=value pair parsed, call handler function with given user
|
||||
pointer as well as section, name, and value (data only valid for duration
|
||||
of handler call). Handler should return nonzero on success, zero on error.
|
||||
|
||||
Returns 0 on success, line number of first error on parse error (doesn't
|
||||
stop on first error), -1 on file open error, or -2 on memory allocation
|
||||
error (only when INI_USE_STACK is zero).
|
||||
*/
|
||||
INI_API int ini_parse(const char* filename, ini_handler handler, void* user);
|
||||
|
||||
/* Same as ini_parse(), but takes a FILE* instead of filename. This doesn't
|
||||
close the file when it's finished -- the caller must do that. */
|
||||
INI_API int ini_parse_file(FILE* file, ini_handler handler, void* user);
|
||||
|
||||
/* Same as ini_parse(), but takes an ini_reader function pointer instead of
|
||||
filename. Used for implementing custom or string-based I/O (see also
|
||||
ini_parse_string). */
|
||||
INI_API int ini_parse_stream(ini_reader reader, void* stream, ini_handler handler,
|
||||
void* user);
|
||||
|
||||
/* Same as ini_parse(), but takes a zero-terminated string with the INI data
|
||||
instead of a file. Useful for parsing INI data from a network socket or
|
||||
which is already in memory. */
|
||||
INI_API int ini_parse_string(const char* string, ini_handler handler, void* user);
|
||||
|
||||
/* Same as ini_parse_string(), but takes a string and its length, avoiding
|
||||
strlen(). Useful for parsing INI data from a network socket or which is
|
||||
already in memory, or interfacing with C++ std::string_view. */
|
||||
INI_API int ini_parse_string_length(const char* string, size_t length, ini_handler handler, void* user);
|
||||
|
||||
/* Nonzero to allow multi-line value parsing, in the style of Python's
|
||||
configparser. If allowed, ini_parse() will call the handler with the same
|
||||
name for each subsequent line parsed. */
|
||||
#ifndef INI_ALLOW_MULTILINE
|
||||
#define INI_ALLOW_MULTILINE 1
|
||||
#endif
|
||||
|
||||
/* Nonzero to allow a UTF-8 BOM sequence (0xEF 0xBB 0xBF) at the start of
|
||||
the file. See https://github.com/benhoyt/inih/issues/21 */
|
||||
#ifndef INI_ALLOW_BOM
|
||||
#define INI_ALLOW_BOM 1
|
||||
#endif
|
||||
|
||||
/* Chars that begin a start-of-line comment. Per Python configparser, allow
|
||||
both ; and # comments at the start of a line by default. */
|
||||
#ifndef INI_START_COMMENT_PREFIXES
|
||||
#define INI_START_COMMENT_PREFIXES ";#"
|
||||
#endif
|
||||
|
||||
/* Nonzero to allow inline comments (with valid inline comment characters
|
||||
specified by INI_INLINE_COMMENT_PREFIXES). Set to 0 to turn off and match
|
||||
Python 3.2+ configparser behaviour. */
|
||||
#ifndef INI_ALLOW_INLINE_COMMENTS
|
||||
#define INI_ALLOW_INLINE_COMMENTS 1
|
||||
#endif
|
||||
#ifndef INI_INLINE_COMMENT_PREFIXES
|
||||
#define INI_INLINE_COMMENT_PREFIXES ";"
|
||||
#endif
|
||||
|
||||
/* Nonzero to use stack for line buffer, zero to use heap (malloc/free). */
|
||||
#ifndef INI_USE_STACK
|
||||
#define INI_USE_STACK 1
|
||||
#endif
|
||||
|
||||
/* Maximum line length for any line in INI file (stack or heap). Note that
|
||||
this must be 3 more than the longest line (due to '\r', '\n', and '\0'). */
|
||||
#ifndef INI_MAX_LINE
|
||||
#define INI_MAX_LINE 200
|
||||
#endif
|
||||
|
||||
/* Nonzero to allow heap line buffer to grow via realloc(), zero for a
|
||||
fixed-size buffer of INI_MAX_LINE bytes. Only applies if INI_USE_STACK is
|
||||
zero. */
|
||||
#ifndef INI_ALLOW_REALLOC
|
||||
#define INI_ALLOW_REALLOC 0
|
||||
#endif
|
||||
|
||||
/* Initial size in bytes for heap line buffer. Only applies if INI_USE_STACK
|
||||
is zero. */
|
||||
#ifndef INI_INITIAL_ALLOC
|
||||
#define INI_INITIAL_ALLOC 200
|
||||
#endif
|
||||
|
||||
/* Stop parsing on first error (default is to keep parsing). */
|
||||
#ifndef INI_STOP_ON_FIRST_ERROR
|
||||
#define INI_STOP_ON_FIRST_ERROR 0
|
||||
#endif
|
||||
|
||||
/* Nonzero to call the handler at the start of each new section (with
|
||||
name and value NULL). Default is to only call the handler on
|
||||
each name=value pair. */
|
||||
#ifndef INI_CALL_HANDLER_ON_NEW_SECTION
|
||||
#define INI_CALL_HANDLER_ON_NEW_SECTION 0
|
||||
#endif
|
||||
|
||||
/* Nonzero to allow a name without a value (no '=' or ':' on the line) and
|
||||
call the handler with value NULL in this case. Default is to treat
|
||||
no-value lines as an error. */
|
||||
#ifndef INI_ALLOW_NO_VALUE
|
||||
#define INI_ALLOW_NO_VALUE 0
|
||||
#endif
|
||||
|
||||
/* Nonzero to use custom ini_malloc, ini_free, and ini_realloc memory
|
||||
allocation functions (INI_USE_STACK must also be 0). These functions must
|
||||
have the same signatures as malloc/free/realloc and behave in a similar
|
||||
way. ini_realloc is only needed if INI_ALLOW_REALLOC is set. */
|
||||
#ifndef INI_CUSTOM_ALLOCATOR
|
||||
#define INI_CUSTOM_ALLOCATOR 0
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* INI_H */
|
||||
20
include/easylog/LICENSE
Normal file
20
include/easylog/LICENSE
Normal file
@ -0,0 +1,20 @@
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2012-present @abumq (Majid Q.)
|
||||
|
||||
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.
|
||||
3116
include/easylog/easylogging++.cc
Normal file
3116
include/easylog/easylogging++.cc
Normal file
File diff suppressed because it is too large
Load Diff
4572
include/easylog/easylogging++.h
Normal file
4572
include/easylog/easylogging++.h
Normal file
File diff suppressed because it is too large
Load Diff
280
main.cpp
Normal file
280
main.cpp
Normal file
@ -0,0 +1,280 @@
|
||||
#include <iostream>
|
||||
#include <stdio.h>
|
||||
#include <fstream>
|
||||
#include <Windows.h>
|
||||
#include <string>
|
||||
#include <tlhelp32.h>
|
||||
#include <sstream>
|
||||
#include <tchar.h>
|
||||
#include "utils/StringHelper.h"
|
||||
#include "src/MemoryCheck.h"
|
||||
#include "easylogging++.h"
|
||||
|
||||
INITIALIZE_EASYLOGGINGPP
|
||||
|
||||
// Windows服务的服务名
|
||||
char SERVICE_NAME[] = "MemoryCheck";
|
||||
SERVICE_STATUS_HANDLE g_ServiceStatusHandle;
|
||||
SERVICE_STATUS g_ServiceStatus;
|
||||
DWORD g_ThreadID;
|
||||
std::wofstream g_ofs;
|
||||
|
||||
// 服务主函数
|
||||
VOID WINAPI ServiceMain(DWORD argc, LPWSTR* argv);
|
||||
|
||||
// 服务控制处理函数
|
||||
VOID WINAPI ServiceCtrlHandler(DWORD CtrlCode);
|
||||
|
||||
|
||||
void EasyLogConf()
|
||||
{
|
||||
////加载默认配置 init log
|
||||
//el::Configurations conf;
|
||||
//////设置为默认
|
||||
////conf.setToDefault();
|
||||
////设置日志输出格式
|
||||
//conf.setGlobally(el::ConfigurationType::Format, "%datetime %level [%fbase|%line] %msg");
|
||||
////设置日志文件目录以及文件名
|
||||
//conf.setGlobally(el::ConfigurationType::Filename, "logs\\%datetime{%Y%M%d}.log");
|
||||
////启用日志
|
||||
//conf.setGlobally(el::ConfigurationType::Enabled, "true");
|
||||
////是否写入文件
|
||||
//conf.setGlobally(el::ConfigurationType::ToFile, "true");
|
||||
////是否输出控制台
|
||||
//conf.setGlobally(el::ConfigurationType::ToStandardOutput, "false");
|
||||
//el::Loggers::reconfigureAllLoggers(conf); //加载配置文件
|
||||
//el::Loggers::addFlag(el::LoggingFlag::HierarchicalLogging);
|
||||
//el::Loggers::setLoggingLevel(el::Level::Debug); //设置日志等级
|
||||
|
||||
string confPath = StringHelper::GetAppPath() + "\log.conf";
|
||||
el::Configurations conf(confPath);
|
||||
el::Loggers::reconfigureAllLoggers(conf);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
int ConsoleMain()
|
||||
{
|
||||
LOG(DEBUG) << "Service is running..." ;
|
||||
MemoryCheck::GetInstance().Init();
|
||||
MemoryCheck::GetInstance().Start();
|
||||
|
||||
MemoryCheck::GetInstance().Stop();
|
||||
LOG(DEBUG) << "Service stoped..." << std::endl;
|
||||
return 0;
|
||||
}
|
||||
|
||||
VOID WINAPI ServiceMain(DWORD argc, LPWSTR* argv)
|
||||
{
|
||||
LOG(DEBUG) << "ServiceMain START...";
|
||||
g_ServiceStatus.dwCurrentState = SERVICE_START_PENDING;
|
||||
g_ServiceStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP;
|
||||
// 注册服务控制处理函数
|
||||
g_ServiceStatusHandle = RegisterServiceCtrlHandler(SERVICE_NAME, ServiceCtrlHandler);
|
||||
if (g_ServiceStatusHandle == NULL)
|
||||
{
|
||||
LOG(ERROR) << "Handler not install";
|
||||
return;
|
||||
}
|
||||
|
||||
SetServiceStatus(g_ServiceStatusHandle, &g_ServiceStatus);
|
||||
|
||||
g_ServiceStatus.dwWin32ExitCode = S_OK;
|
||||
g_ServiceStatus.dwCheckPoint = 0;
|
||||
g_ServiceStatus.dwWaitHint = 0;
|
||||
g_ServiceStatus.dwCurrentState = SERVICE_RUNNING;
|
||||
SetServiceStatus(g_ServiceStatusHandle, &g_ServiceStatus);
|
||||
|
||||
// 在 ServiceMain 中调用控制台程序的主函数
|
||||
ConsoleMain();
|
||||
|
||||
// 设置服务状态为停止
|
||||
g_ServiceStatus.dwCurrentState = SERVICE_STOPPED;
|
||||
g_ServiceStatus.dwCheckPoint = 0;
|
||||
g_ServiceStatus.dwWaitHint = 0;
|
||||
|
||||
if (!SetServiceStatus(g_ServiceStatusHandle, &g_ServiceStatus)){
|
||||
LOG(ERROR) << "SetServiceStatus failed, error code: " << GetLastError();
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
void Init()
|
||||
{
|
||||
g_ServiceStatusHandle = NULL;
|
||||
g_ServiceStatus.dwServiceType = SERVICE_WIN32_OWN_PROCESS | SERVICE_INTERACTIVE_PROCESS;
|
||||
g_ServiceStatus.dwCurrentState = SERVICE_START_PENDING;
|
||||
g_ServiceStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP;
|
||||
g_ServiceStatus.dwWin32ExitCode = 0;
|
||||
g_ServiceStatus.dwServiceSpecificExitCode = 0;
|
||||
g_ServiceStatus.dwCheckPoint = 0;
|
||||
g_ServiceStatus.dwWaitHint = 0;
|
||||
}
|
||||
|
||||
|
||||
bool IsInstalled()
|
||||
{
|
||||
SC_HANDLE hSCM = ::OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
|
||||
if (hSCM == NULL) {
|
||||
LOG(ERROR) << "OpenSCManager error..."<<GetLastError();
|
||||
return false;
|
||||
}
|
||||
|
||||
SC_HANDLE hService = ::OpenService(hSCM, SERVICE_NAME, SERVICE_QUERY_CONFIG);
|
||||
if (hService == NULL) {
|
||||
::CloseServiceHandle(hSCM);
|
||||
DWORD err = GetLastError();
|
||||
if (err == ERROR_SERVICE_DOES_NOT_EXIST) {
|
||||
LOG(INFO) << "Service is not installed";
|
||||
return false;
|
||||
}
|
||||
else {
|
||||
LOG(ERROR) << "OpenService error..." << GetLastError();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
::CloseServiceHandle(hService);
|
||||
::CloseServiceHandle(hSCM);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool Install()
|
||||
{
|
||||
if (IsInstalled())return true;
|
||||
SC_HANDLE hSCM = ::OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
|
||||
if (hSCM == NULL)return false;
|
||||
TCHAR szFilePath[MAX_PATH];
|
||||
::GetModuleFileName(NULL, szFilePath, MAX_PATH);
|
||||
|
||||
SC_HANDLE hService = ::CreateService(hSCM, SERVICE_NAME, SERVICE_NAME, SERVICE_ALL_ACCESS,
|
||||
SERVICE_WIN32_OWN_PROCESS | SERVICE_INTERACTIVE_PROCESS, SERVICE_AUTO_START, SERVICE_ERROR_NORMAL,
|
||||
szFilePath, NULL, NULL, _T(""), NULL, NULL);
|
||||
if (hService == NULL) {
|
||||
::CloseServiceHandle(hSCM);
|
||||
LOG(ERROR) << "CreateService false...error:"<<GetLastError();
|
||||
return false;
|
||||
}
|
||||
|
||||
// 创建服务后立即启动
|
||||
if (!StartService(hService, 0, NULL)){
|
||||
LOG(ERROR) << "StartService false...error:"<<GetLastError();
|
||||
}
|
||||
else {
|
||||
LOG(DEBUG) << "服务启动成功...";
|
||||
}
|
||||
|
||||
::CloseServiceHandle(hService);
|
||||
::CloseServiceHandle(hSCM);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool Uninstall()
|
||||
{
|
||||
SC_HANDLE schSCManager;
|
||||
SC_HANDLE schService;
|
||||
|
||||
schSCManager = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
|
||||
if (schSCManager == NULL){
|
||||
LOG(ERROR) << " 打开SCManager失败:" << GetLastError();
|
||||
return false;
|
||||
}
|
||||
|
||||
schService = OpenService(schSCManager, SERVICE_NAME, SERVICE_ALL_ACCESS);
|
||||
if (schService == NULL) {
|
||||
LOG(ERROR) << "打开服务失败:" << GetLastError();
|
||||
CloseServiceHandle(schSCManager);
|
||||
return false;
|
||||
}
|
||||
|
||||
bool result = true;
|
||||
SERVICE_STATUS status;
|
||||
::ControlService(schService, SERVICE_CONTROL_STOP, &status);
|
||||
if (!DeleteService(schService)){
|
||||
LOG(ERROR) << "删除服务失败:" << GetLastError();
|
||||
result = false;
|
||||
}
|
||||
else{
|
||||
LOG(ERROR) << "服务删除成功" ;
|
||||
}
|
||||
|
||||
CloseServiceHandle(schService);
|
||||
CloseServiceHandle(schSCManager);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
|
||||
VOID WINAPI ServiceCtrlHandler(DWORD CtrlCode)
|
||||
{
|
||||
switch (CtrlCode)
|
||||
{
|
||||
case SERVICE_CONTROL_STOP:
|
||||
//设置服务状态为停止
|
||||
g_ServiceStatus.dwCurrentState = SERVICE_STOP_PENDING;
|
||||
g_ServiceStatus.dwCheckPoint = 1;
|
||||
|
||||
if (!SetServiceStatus(g_ServiceStatusHandle, &g_ServiceStatus))
|
||||
{
|
||||
std::cerr << "SetServiceStatus failed, error code: " << GetLastError() << std::endl;
|
||||
}
|
||||
Sleep(500);
|
||||
// 设置服务状态为停止
|
||||
g_ServiceStatus.dwCurrentState = SERVICE_STOPPED;
|
||||
g_ServiceStatus.dwCheckPoint = 0;
|
||||
g_ServiceStatus.dwWaitHint = 0;
|
||||
|
||||
if (!SetServiceStatus(g_ServiceStatusHandle, &g_ServiceStatus))
|
||||
{
|
||||
std::cerr << "SetServiceStatus failed, error code: " << GetLastError() << std::endl;
|
||||
}
|
||||
|
||||
PostThreadMessage(g_ThreadID, WM_CLOSE, 0, 0);
|
||||
break;
|
||||
case SERVICE_CONTROL_SHUTDOWN:
|
||||
exit(0);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int APIENTRY _tWinMain(HINSTANCE hinstance, HINSTANCE hPrevInstance, LPTSTR lpCmdLine, int nCmdShow){
|
||||
EasyLogConf(); //easylog配置
|
||||
|
||||
Init();
|
||||
g_ThreadID = ::GetCurrentThreadId();
|
||||
SERVICE_TABLE_ENTRY ServiceTable[] =
|
||||
{
|
||||
{ SERVICE_NAME, (LPSERVICE_MAIN_FUNCTION)ServiceMain },
|
||||
{ NULL, NULL }
|
||||
};
|
||||
|
||||
if (strcmp(lpCmdLine, "/install") == 0) {
|
||||
LOG(DEBUG) << "install start...";
|
||||
Install();
|
||||
}
|
||||
else if (strcmp(lpCmdLine, "/uninstall") == 0)
|
||||
{
|
||||
LOG(DEBUG) << "uninstall start...";
|
||||
if (!Uninstall()) {
|
||||
LOG(DEBUG) << "uninstall error(" << GetLastError() << ")...";
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (!::StartServiceCtrlDispatcher(ServiceTable))
|
||||
{
|
||||
LOG(DEBUG) << "start error(" << GetLastError() << ")...";
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
}
|
||||
9
resource/config.ini
Normal file
9
resource/config.ini
Normal file
@ -0,0 +1,9 @@
|
||||
; Test config file for ini_example.c and INIReaderTest.cpp
|
||||
|
||||
[MemCheck]
|
||||
UpLimit=80 ; 内存检测上限%
|
||||
CheckInterval = 4 ; 检测时间间隔s
|
||||
|
||||
[whitelist] ; 白名单
|
||||
value = HBDSystemE1000Pro
|
||||
value = HBDSystemE1000Pro
|
||||
8
resource/install.bat
Normal file
8
resource/install.bat
Normal file
@ -0,0 +1,8 @@
|
||||
|
||||
cd /d "%~dp0"
|
||||
echo Current directory: %CD%
|
||||
|
||||
MemoryCheck.exe /install
|
||||
|
||||
|
||||
pause
|
||||
18
resource/log.conf
Normal file
18
resource/log.conf
Normal file
@ -0,0 +1,18 @@
|
||||
* GLOBAL:
|
||||
FORMAT = "%datetime %level [%fbase|%line] %msg"
|
||||
FILENAME = "logs\\%datetime{%Y%M%d}.log"
|
||||
ENABLED = true
|
||||
TO_FILE = true ## Notice this
|
||||
TO_STANDARD_OUTPUT = false ## Notice this
|
||||
SUBSECOND_PRECISION = 3
|
||||
PERFORMANCE_TRACKING = false
|
||||
MAX_LOG_FILE_SIZE = 2097152 ## Throw log files away after 2MB
|
||||
|
||||
* DEBUG:
|
||||
ENABLED = true
|
||||
* TRACE:
|
||||
ENABLED = false
|
||||
* INFO:
|
||||
ENABLED = true
|
||||
* ERROR:
|
||||
ENABLED = true
|
||||
BIN
resource/pskill.exe
Normal file
BIN
resource/pskill.exe
Normal file
Binary file not shown.
BIN
resource/pslist.exe
Normal file
BIN
resource/pslist.exe
Normal file
Binary file not shown.
9
resource/uninstall.bat
Normal file
9
resource/uninstall.bat
Normal file
@ -0,0 +1,9 @@
|
||||
|
||||
cd /d "%~dp0"
|
||||
echo Current directory: %CD%
|
||||
|
||||
MemoryCheck.exe /uninstall
|
||||
pause
|
||||
|
||||
|
||||
|
||||
53
src/Config.h
Normal file
53
src/Config.h
Normal file
@ -0,0 +1,53 @@
|
||||
#pragma once
|
||||
#include <iostream>
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include "INIReader.h"
|
||||
#include "../utils/StringHelper.h"
|
||||
#include "easylogging++.h"
|
||||
using namespace std;
|
||||
|
||||
class Config {
|
||||
|
||||
public :
|
||||
Config():m_MemCheckUpLimit(90), m_CheckInterval(60){}
|
||||
~Config() {}
|
||||
|
||||
void Init() {
|
||||
string appPath = StringHelper::GetAppPath();
|
||||
string iniPath = appPath + "\config.ini";
|
||||
INIReader reader(iniPath);
|
||||
LOG(DEBUG) << "iniPath:" << iniPath;
|
||||
|
||||
if (reader.ParseError() < 0) {
|
||||
LOG(ERROR) << iniPath << " load error!";
|
||||
return;
|
||||
}
|
||||
|
||||
m_MemCheckUpLimit = reader.GetReal("MemCheck", "UpLimit", 90);
|
||||
m_CheckInterval = reader.GetReal("MemCheck", "CheckInterval", 120);
|
||||
LOG(TRACE) << m_MemCheckUpLimit;
|
||||
string whiteList = reader.Get("whitelist", "value", "UNKNOW");
|
||||
istringstream iss(whiteList);
|
||||
string line;
|
||||
while (iss >> line) {
|
||||
m_Whitelists.emplace_back(line);
|
||||
LOG(TRACE) << "line:" << line;
|
||||
}
|
||||
}
|
||||
|
||||
bool InWhitelists(string& processName) {
|
||||
bool isFind = false;
|
||||
for (auto it : m_Whitelists) {
|
||||
if (processName == it) {
|
||||
isFind = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return isFind;
|
||||
}
|
||||
|
||||
float m_MemCheckUpLimit; //内存检测上限
|
||||
float m_CheckInterval; //检测时间间隔s
|
||||
vector<string> m_Whitelists; //白名单
|
||||
};
|
||||
29
src/MemDefine.h
Normal file
29
src/MemDefine.h
Normal file
@ -0,0 +1,29 @@
|
||||
#pragma once
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
using namespace std;
|
||||
|
||||
class MemoryCheckLog
|
||||
{
|
||||
public:
|
||||
MemoryCheckLog()
|
||||
: m_Id(0)
|
||||
, m_InsertTime(0)
|
||||
, m_Pid(0)
|
||||
, m_PagefileUsageMB(0.0f)
|
||||
, m_WorkingSetMB(0.0f)
|
||||
, m_PrivateUsageMB(0.0f)
|
||||
, m_SharedCommitMB(0.0f){}
|
||||
~MemoryCheckLog() {}
|
||||
|
||||
public:
|
||||
uint64_t m_Id;
|
||||
time_t m_InsertTime;
|
||||
uint32_t m_Pid;
|
||||
string m_ProcessName;
|
||||
float m_PagefileUsageMB; // 提交内存(MB)
|
||||
float m_WorkingSetMB; // 物理内存(MB)
|
||||
float m_PrivateUsageMB; //专用内存
|
||||
float m_SharedCommitMB;
|
||||
|
||||
};
|
||||
609
src/MemoryCheck.cpp
Normal file
609
src/MemoryCheck.cpp
Normal file
@ -0,0 +1,609 @@
|
||||
#include "MemoryCheck.h"
|
||||
#include <algorithm>
|
||||
#include <tlhelp32.h>
|
||||
#include <sstream>
|
||||
#include <shellapi.h>
|
||||
#include <Windows.h>
|
||||
#include <iostream>
|
||||
#include <stdio.h>
|
||||
#include <fstream>
|
||||
#include <Windows.h>
|
||||
#include <string>
|
||||
#include <tlhelp32.h>
|
||||
#include <sstream>
|
||||
#include "../utils/StringHelper.h"
|
||||
#include "easylogging++.h"
|
||||
|
||||
/*
|
||||
NTSYSCALLAPI NTSTATUS NTAPI
|
||||
NtQuerySystemInformation(
|
||||
_In_ SYSTEM_INFORMATION_CLASS SystemInformationClass,
|
||||
_Out_writes_bytes_opt_(SystemInformationLength) PVOID SystemInformation,
|
||||
_In_ ULONG SystemInformationLength,
|
||||
_Out_opt_ PULONG ReturnLength
|
||||
);
|
||||
|
||||
|
||||
NTSYSAPI
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
NtQuerySystemInformation(
|
||||
_In_ SYSTEM_INFORMATION_CLASS SystemInformationClass,
|
||||
_In_ PVOID NativeSystemInformation,
|
||||
_In_ ULONG InformationLength,
|
||||
_Out_opt_ PULONG ReturnLength
|
||||
);
|
||||
*/
|
||||
|
||||
MemoryCheck::~MemoryCheck() {
|
||||
Stop();
|
||||
}
|
||||
|
||||
void MemoryCheck::Init()
|
||||
{
|
||||
m_HNtDll = GetModuleHandle("ntdll.dll");
|
||||
if (m_HNtDll) {
|
||||
NtQuerySystemInformation = (PNTQUERYSYSTEMINFORMATION)GetProcAddress(m_HNtDll, "NtQuerySystemInformation");
|
||||
if (NtQuerySystemInformation) {
|
||||
InitializeWindowsInformation();
|
||||
m_UseSysApi = true;
|
||||
NtQueryInformationProcess = (pNtQueryInformationProcess)GetProcAddress(m_HNtDll, "NtQueryInformationProcess");
|
||||
if (NtQueryInformationProcess)
|
||||
{
|
||||
m_EnableProcessExtension = m_WindowsVersion >= WINDOWS_10_RS3 && !PhIsExecutingInWow64();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
//m_AlarmCfgWrapper = ConfigManager::GetInstance()->GetAlarmCfg();
|
||||
|
||||
|
||||
m_Config = new Config();
|
||||
m_Config->Init();
|
||||
}
|
||||
|
||||
void MemoryCheck::Start()
|
||||
{
|
||||
if (m_Running) return;
|
||||
m_Running = true;
|
||||
MonitorProc();
|
||||
//m_MonitorThread = std::thread(&MemoryCheck::MonitorProc, this);
|
||||
//SetThreadPriority(m_MonitorThread.native_handle(), THREAD_PRIORITY_BELOW_NORMAL);
|
||||
}
|
||||
|
||||
void MemoryCheck::Stop()
|
||||
{
|
||||
m_Running = false;
|
||||
//if (m_MonitorThread.joinable()) {
|
||||
// m_MonitorThread.join();
|
||||
//}
|
||||
}
|
||||
|
||||
NTSTATUS MemoryCheck::HbEnumProcesses(PVOID* Processes)
|
||||
{
|
||||
static ULONG initialBufferSize[3] = { 0x4000, 0x4000, 0x4000 };
|
||||
NTSTATUS status;
|
||||
ULONG classIndex;
|
||||
PVOID buffer;
|
||||
ULONG bufferSize;
|
||||
classIndex = 0;
|
||||
bufferSize = initialBufferSize[classIndex];
|
||||
buffer = malloc(bufferSize);
|
||||
if (!buffer) return STATUS_NO_MEMORY;
|
||||
|
||||
while (TRUE)
|
||||
{
|
||||
status = NtQuerySystemInformation(
|
||||
SystemProcessInformation,
|
||||
buffer,
|
||||
bufferSize,
|
||||
&bufferSize
|
||||
);
|
||||
|
||||
if (status == STATUS_BUFFER_TOO_SMALL || status == STATUS_INFO_LENGTH_MISMATCH)
|
||||
{
|
||||
free(buffer);
|
||||
buffer = malloc(bufferSize);
|
||||
if (!buffer) return STATUS_NO_MEMORY;
|
||||
}
|
||||
else
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!NT_SUCCESS(status))
|
||||
{
|
||||
free(buffer);
|
||||
return status;
|
||||
}
|
||||
|
||||
if (bufferSize <= 0x100000) initialBufferSize[classIndex] = bufferSize;
|
||||
*Processes = buffer;
|
||||
return status;
|
||||
}
|
||||
|
||||
std::vector<MemoryCheckLog> MemoryCheck::GetTopProcesses(int topN) {
|
||||
std::vector<MemoryCheckLog> processes;
|
||||
|
||||
string pslistPath = GetAppPath() + "pslist.exe";
|
||||
HANDLE hReadPipe, hWritePipe;
|
||||
SECURITY_ATTRIBUTES sa = { sizeof(SECURITY_ATTRIBUTES), NULL, TRUE };
|
||||
if (!CreatePipe(&hReadPipe, &hWritePipe, &sa, 0)) {
|
||||
return processes;
|
||||
}
|
||||
STARTUPINFOA si = { sizeof(si) };
|
||||
PROCESS_INFORMATION pi = {};
|
||||
|
||||
si.dwFlags = STARTF_USESTDHANDLES;
|
||||
si.hStdOutput = hWritePipe;
|
||||
si.hStdError = hWritePipe;
|
||||
si.hStdInput = NULL;
|
||||
|
||||
char cmdLine[512];
|
||||
sprintf_s(cmdLine, sizeof(cmdLine), "%s /accepteula -m", pslistPath.c_str());
|
||||
if (!CreateProcess(NULL, cmdLine, NULL, NULL, TRUE, CREATE_NO_WINDOW, NULL, NULL, &si, &pi))
|
||||
{
|
||||
CloseHandle(hReadPipe);
|
||||
CloseHandle(hWritePipe);
|
||||
return processes;
|
||||
}
|
||||
|
||||
CloseHandle(hWritePipe); // 关闭写端,让读操作能结束
|
||||
char buffer[4096];
|
||||
DWORD bytesRead;
|
||||
stringstream output;
|
||||
while (ReadFile(hReadPipe, buffer, sizeof(buffer) - 1, &bytesRead, NULL) && bytesRead > 0) {
|
||||
buffer[bytesRead] = '\0';
|
||||
output << buffer;
|
||||
}
|
||||
|
||||
std::string line;
|
||||
bool headerSkipped = false;
|
||||
while (std::getline(output, line)) {
|
||||
// 跳过标题行和表头
|
||||
if (!headerSkipped) {
|
||||
if (line.find("Name") != std::string::npos && line.find("Pid") != std::string::npos)
|
||||
headerSkipped = true;
|
||||
continue;
|
||||
}
|
||||
//OutputDebugString(line.c_str());
|
||||
// 解析行内容
|
||||
std::istringstream lineStream(line);
|
||||
std::vector<std::string> tokens;
|
||||
std::string token;
|
||||
while (lineStream >> token) {
|
||||
tokens.push_back(token);
|
||||
}
|
||||
|
||||
if (tokens.size() < 9) {
|
||||
continue;
|
||||
}
|
||||
try {
|
||||
MemoryCheckLog log;
|
||||
size_t N = tokens.size();
|
||||
log.m_Pid = std::stoul(tokens[N - 8]);
|
||||
log.m_WorkingSetMB = SafeToDouble(tokens[N - 6]) / 1024.0;
|
||||
log.m_PagefileUsageMB = SafeToDouble(tokens[N - 5]) / 1024.0;
|
||||
|
||||
std::ostringstream nameStream;
|
||||
for (size_t i = 0; i < N - 8; ++i) {
|
||||
if (i > 0) nameStream << " ";
|
||||
nameStream << tokens[i];
|
||||
}
|
||||
log.m_ProcessName = nameStream.str();
|
||||
|
||||
processes.push_back(log);
|
||||
}
|
||||
catch (...) {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
CloseHandle(hReadPipe);
|
||||
WaitForSingleObject(pi.hProcess, INFINITE);
|
||||
CloseHandle(pi.hProcess);
|
||||
CloseHandle(pi.hThread);
|
||||
|
||||
|
||||
|
||||
// 按内存排序
|
||||
std::sort(processes.begin(), processes.end(), [](const MemoryCheckLog& a, const MemoryCheckLog& b) {
|
||||
return a.m_PagefileUsageMB > b.m_PagefileUsageMB;
|
||||
});
|
||||
|
||||
if (topN > 0 && topN < processes.size()) {
|
||||
processes.resize(topN);
|
||||
}
|
||||
return processes;
|
||||
}
|
||||
|
||||
std::vector<MemoryCheckLog> MemoryCheck::GetTopProcesses2(int topN) {
|
||||
std::vector<MemoryCheckLog> checks;
|
||||
NTSTATUS status;
|
||||
PVOID processes;
|
||||
if (!NT_SUCCESS(status = HbEnumProcesses(&processes)))
|
||||
{
|
||||
return checks;
|
||||
}
|
||||
PSYSTEM_PROCESS_INFORMATION process;
|
||||
process = PH_FIRST_PROCESS(processes);
|
||||
while (process)
|
||||
{
|
||||
PSYSTEM_PROCESS_INFORMATION_EXTENSION processExtension;
|
||||
processExtension = PH_PROCESS_EXTENSION(process);
|
||||
if (process->ImageName.Buffer) {
|
||||
string str = StringHelper::Wstr2Str(process->ImageName.Buffer);
|
||||
if (!str.empty()) {
|
||||
MemoryCheckLog log;
|
||||
log.m_ProcessName = str;
|
||||
log.m_Pid = (uint32_t)process->UniqueProcessId;
|
||||
log.m_WorkingSetMB = (double)process->WorkingSetSize / 1024.0 / 1024.0;
|
||||
log.m_PagefileUsageMB = (double)process->PagefileUsage / 1024.0 / 1024.0;
|
||||
log.m_PrivateUsageMB = (double)process->WorkingSetPrivateSize / 1024.0 / 1024.0;
|
||||
log.m_SharedCommitMB = (double)processExtension->SharedCommitCharge / 1024.0 / 1024.0;
|
||||
checks.push_back(log);
|
||||
//if (g_isDebug)
|
||||
//{
|
||||
// char buffer[512];
|
||||
// sprintf_s(buffer, sizeof(buffer), "name=%s\tpid=%u\tWorkingSetMB=%.2f\tPagefileUsage(MB)=%.2f\tPrivateUsage(MB)=%.2f\tSharedCommit(MB)=%.2f\n",
|
||||
// log.m_ProcessName.c_str(), log.m_Pid, log.m_WorkingSetMB, log.m_PagefileUsageMB, log.m_PrivateUsageMB, log.m_SharedCommitMB);
|
||||
// OutputDebugString(buffer);
|
||||
//}
|
||||
}
|
||||
}
|
||||
process = PH_NEXT_PROCESS(process);
|
||||
}
|
||||
free(processes);
|
||||
// 按内存排序
|
||||
std::sort(checks.begin(), checks.end(), [](const MemoryCheckLog& a, const MemoryCheckLog& b) {
|
||||
float biga = a.m_PagefileUsageMB > a.m_SharedCommitMB ? a.m_PagefileUsageMB : a.m_SharedCommitMB;
|
||||
float bigb = b.m_PagefileUsageMB > b.m_SharedCommitMB ? b.m_PagefileUsageMB : b.m_SharedCommitMB;
|
||||
return biga > bigb;
|
||||
});
|
||||
|
||||
if (topN > 0 && topN < checks.size()) {
|
||||
checks.resize(topN);
|
||||
}
|
||||
return checks;
|
||||
}
|
||||
void MemoryCheck::MonitorProc() {
|
||||
int checkFlag = m_Config->m_CheckInterval*1000 / 100;
|
||||
while (m_Running) {
|
||||
CheckAndAlert();
|
||||
int count = 0;
|
||||
while (m_Running && (count < checkFlag)) {
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(100));
|
||||
count++;
|
||||
}
|
||||
//LOG(WARNING) << "MonitorProc is run...";
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void MemoryCheck::CheckAndAlert() {
|
||||
MEMORYSTATUSEX memStatus = { 0 };
|
||||
memStatus.dwLength = sizeof(memStatus);
|
||||
GlobalMemoryStatusEx(&memStatus);
|
||||
|
||||
|
||||
// 计算关键指标
|
||||
double physicalMemoryUsagePercent = 100.0 * (memStatus.ullTotalPhys - memStatus.ullAvailPhys) / memStatus.ullTotalPhys;
|
||||
|
||||
double systemCommitUsagePercent = 100.0 * (memStatus.ullTotalPageFile - memStatus.ullAvailPageFile) / memStatus.ullTotalPageFile;
|
||||
|
||||
|
||||
if (physicalMemoryUsagePercent < m_Config->m_MemCheckUpLimit && systemCommitUsagePercent < m_Config->m_MemCheckUpLimit)
|
||||
{
|
||||
//SignalService::GetInstance().SetAlarm(m_AlarmCfgWrapper->m_MemoryLeakWarn, false);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
auto topProcesses = GetTopProcesses2(5);
|
||||
for(size_t i = 0; i < topProcesses.size(); ++i) {
|
||||
char buff[512] = { 0 };
|
||||
for (auto a : topProcesses) {
|
||||
sprintf_s(buff, sizeof(buff) - 1, "Pid:%u,ProcessName:%s,PagefileUsageMB:%.2f,WorkingSetMB:%.2f,PrivateUsageMB:%.2f,SharedCommitMB:%.2f",
|
||||
a.m_Pid, a.m_ProcessName.c_str(), a.m_PagefileUsageMB, a.m_WorkingSetMB, a.m_PrivateUsageMB, a.m_SharedCommitMB);
|
||||
LOG(TRACE) << "Top Processes:"<<buff;
|
||||
}
|
||||
|
||||
DWORD pid = GetCurrentProcessId();
|
||||
MemoryCheckLog log;
|
||||
bool needClose = false;
|
||||
log = topProcesses[i];
|
||||
|
||||
if (m_Config->InWhitelists(log.m_ProcessName)) {
|
||||
LOG(TRACE) << log.m_ProcessName << u8"在白名单不关闭...";
|
||||
continue;
|
||||
}
|
||||
|
||||
needClose = (log.m_Pid != pid);
|
||||
#ifdef _DEBUG
|
||||
if (needClose) {
|
||||
log.m_ProcessName = "notepad++";
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
if (needClose) {
|
||||
LOG(INFO) << u8"尝试关闭" << log.m_ProcessName.c_str();
|
||||
string pskillPath = GetAppPath() + "pskill.exe";
|
||||
char cmd[512];
|
||||
sprintf_s(cmd, sizeof(cmd), "%s /accepteula %s", pskillPath.c_str(), log.m_ProcessName.c_str());
|
||||
HANDLE hReadPipe, hWritePipe;
|
||||
SECURITY_ATTRIBUTES sa = { sizeof(SECURITY_ATTRIBUTES), NULL, TRUE };
|
||||
if (!CreatePipe(&hReadPipe, &hWritePipe, &sa, 0)) {
|
||||
//m_AlarmCfgWrapper->m_MemoryLeakWarn->m_AlarmInfo = "";
|
||||
return;
|
||||
}
|
||||
STARTUPINFOA si = { sizeof(si) };
|
||||
PROCESS_INFORMATION pi = {};
|
||||
|
||||
si.dwFlags = STARTF_USESTDHANDLES;
|
||||
si.hStdOutput = hWritePipe;
|
||||
si.hStdError = hWritePipe;
|
||||
si.hStdInput = NULL;
|
||||
if (!CreateProcess(NULL, cmd, NULL, NULL, TRUE, CREATE_NO_WINDOW, NULL, NULL, &si, &pi))
|
||||
{
|
||||
CloseHandle(hReadPipe);
|
||||
CloseHandle(hWritePipe);
|
||||
//m_AlarmCfgWrapper->m_MemoryLeakWarn->m_AlarmInfo = "";
|
||||
return;
|
||||
}
|
||||
|
||||
CloseHandle(hWritePipe); // 关闭写端,让读操作能结束
|
||||
char buffer[4096];
|
||||
DWORD bytesRead;
|
||||
stringstream output;
|
||||
while (ReadFile(hReadPipe, buffer, sizeof(buffer) - 1, &bytesRead, NULL) && bytesRead > 0) {
|
||||
buffer[bytesRead] = '\0';
|
||||
output << buffer;
|
||||
}
|
||||
|
||||
CloseHandle(hReadPipe);
|
||||
WaitForSingleObject(pi.hProcess, INFINITE);
|
||||
CloseHandle(pi.hProcess);
|
||||
CloseHandle(pi.hThread);
|
||||
string outstr = output.str();
|
||||
if (outstr.find("killed") != string::npos)
|
||||
{
|
||||
sprintf_s(buffer, sizeof(buffer),u8"关闭%s成功", log.m_ProcessName.c_str());
|
||||
LOG(DEBUG) << buffer;
|
||||
|
||||
if (log.m_ProcessName == "explorer" || log.m_ProcessName == "Explorer" || log.m_ProcessName == "EXPLORER") {
|
||||
Sleep(2000);
|
||||
SHELLEXECUTEINFO sei = { sizeof(sei) };
|
||||
sei.lpFile = "explorer.exe";
|
||||
sei.lpDirectory = "C:\\Windows";
|
||||
sei.nShow = SW_SHOWNORMAL;
|
||||
ShellExecuteEx(&sei);
|
||||
}
|
||||
break;
|
||||
}
|
||||
else {
|
||||
sprintf_s(buffer, sizeof(buffer),u8"关闭%s失败", log.m_ProcessName.c_str());
|
||||
LOG(WARNING) << buffer;
|
||||
}
|
||||
}
|
||||
}
|
||||
//m_AlarmCfgWrapper->m_MemoryLeakWarn->m_LastAlarmFlag = false;
|
||||
//SignalService::GetInstance().SetAlarm(m_AlarmCfgWrapper->m_MemoryLeakWarn, true);
|
||||
|
||||
}
|
||||
|
||||
MemoryCheckLog MemoryCheck::GetWinProcessInfo(DWORD pid) {
|
||||
MemoryCheckLog info;
|
||||
info.m_Pid = pid;
|
||||
HANDLE hProcess = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, pid);
|
||||
if (!hProcess) return info;
|
||||
|
||||
// char name[MAX_PATH] = "";
|
||||
// if (GetModuleBaseName(hProcess, NULL, name, sizeof(name))) {
|
||||
// info.m_ProcessName = name;
|
||||
// }
|
||||
|
||||
PROCESS_MEMORY_COUNTERS_EX pmc;
|
||||
pmc.cb = sizeof(pmc);
|
||||
if (GetProcessMemoryInfo(hProcess, (PROCESS_MEMORY_COUNTERS*)&pmc, sizeof(pmc))) {
|
||||
info.m_PagefileUsageMB = (double)pmc.PagefileUsage / 1024.0 / 1024.0;
|
||||
info.m_WorkingSetMB = (double)pmc.WorkingSetSize / 1024.0 / 1024.0;
|
||||
info.m_PrivateUsageMB = (double)pmc.PrivateUsage / 1024.0 / 1024.0;
|
||||
}
|
||||
|
||||
CloseHandle(hProcess);
|
||||
return info;
|
||||
}
|
||||
|
||||
// 将字符串转 float,出错返回 0
|
||||
double MemoryCheck::SafeToDouble(const std::string& str) {
|
||||
try {
|
||||
return std::stod(str);
|
||||
}
|
||||
catch (...) {
|
||||
return 0.0;
|
||||
}
|
||||
}
|
||||
|
||||
typedef NTSTATUS(NTAPI* PRtlGetVersion)(_Out_ PVOID VersionInformation);
|
||||
void MemoryCheck::InitializeWindowsInformation()
|
||||
{
|
||||
auto RtlGetVersion = (PRtlGetVersion)GetProcAddress(m_HNtDll, "RtlGetVersion");
|
||||
NTSTATUS status;
|
||||
RTL_OSVERSIONINFOEX versionInfo;
|
||||
ULONG majorVersion;
|
||||
ULONG minorVersion;
|
||||
ULONG buildVersion;
|
||||
|
||||
memset(&versionInfo, 0, sizeof(RTL_OSVERSIONINFOEX));
|
||||
versionInfo.OSVersionInfoSize = sizeof(RTL_OSVERSIONINFOEX);
|
||||
|
||||
if (!NT_SUCCESS(status = RtlGetVersion(&versionInfo)))
|
||||
{
|
||||
m_WindowsVersion = WINDOWS_ANCIENT;
|
||||
return;
|
||||
}
|
||||
RTL_OSVERSIONINFOEX PhOsVersion = { 0 };
|
||||
memcpy(&PhOsVersion, &versionInfo, sizeof(RTL_OSVERSIONINFOEX));
|
||||
majorVersion = versionInfo.MajorVersion;
|
||||
minorVersion = versionInfo.MinorVersion;
|
||||
buildVersion = versionInfo.BuildNumber;
|
||||
|
||||
if (majorVersion == 6 && minorVersion < 1 || majorVersion < 6)
|
||||
{
|
||||
m_WindowsVersion = WINDOWS_ANCIENT;
|
||||
}
|
||||
// Windows 7, Windows Server 2008 R2
|
||||
else if (majorVersion == 6 && minorVersion == 1)
|
||||
{
|
||||
m_WindowsVersion = WINDOWS_7;
|
||||
}
|
||||
// Windows 8, Windows Server 2012
|
||||
else if (majorVersion == 6 && minorVersion == 2)
|
||||
{
|
||||
m_WindowsVersion = WINDOWS_8;
|
||||
}
|
||||
// Windows 8.1, Windows Server 2012 R2
|
||||
else if (majorVersion == 6 && minorVersion == 3)
|
||||
{
|
||||
m_WindowsVersion = WINDOWS_8_1;
|
||||
}
|
||||
// Windows 10, Windows Server 2016
|
||||
else if (majorVersion == 10 && minorVersion == 0)
|
||||
{
|
||||
if (buildVersion > 26100)
|
||||
{
|
||||
m_WindowsVersion = WINDOWS_NEW;
|
||||
}
|
||||
else if (buildVersion >= 26100)
|
||||
{
|
||||
m_WindowsVersion = WINDOWS_11_24H2;
|
||||
}
|
||||
else if (buildVersion >= 22631)
|
||||
{
|
||||
m_WindowsVersion = WINDOWS_11_23H2;
|
||||
}
|
||||
else if (buildVersion >= 22621)
|
||||
{
|
||||
m_WindowsVersion = WINDOWS_11_22H2;
|
||||
}
|
||||
else if (buildVersion >= 22000)
|
||||
{
|
||||
m_WindowsVersion = WINDOWS_11;
|
||||
}
|
||||
else if (buildVersion >= 19045)
|
||||
{
|
||||
m_WindowsVersion = WINDOWS_10_22H2;
|
||||
}
|
||||
else if (buildVersion >= 19044)
|
||||
{
|
||||
m_WindowsVersion = WINDOWS_10_21H2;
|
||||
}
|
||||
else if (buildVersion >= 19043)
|
||||
{
|
||||
m_WindowsVersion = WINDOWS_10_21H1;
|
||||
}
|
||||
else if (buildVersion >= 19042)
|
||||
{
|
||||
m_WindowsVersion = WINDOWS_10_20H2;
|
||||
}
|
||||
else if (buildVersion >= 19041)
|
||||
{
|
||||
m_WindowsVersion = WINDOWS_10_20H1;
|
||||
}
|
||||
else if (buildVersion >= 18363)
|
||||
{
|
||||
m_WindowsVersion = WINDOWS_10_19H2;
|
||||
}
|
||||
else if (buildVersion >= 18362)
|
||||
{
|
||||
m_WindowsVersion = WINDOWS_10_19H1;
|
||||
}
|
||||
else if (buildVersion >= 17763)
|
||||
{
|
||||
m_WindowsVersion = WINDOWS_10_RS5;
|
||||
}
|
||||
else if (buildVersion >= 17134)
|
||||
{
|
||||
m_WindowsVersion = WINDOWS_10_RS4;
|
||||
}
|
||||
else if (buildVersion >= 16299)
|
||||
{
|
||||
m_WindowsVersion = WINDOWS_10_RS3;
|
||||
}
|
||||
else if (buildVersion >= 15063)
|
||||
{
|
||||
m_WindowsVersion = WINDOWS_10_RS2;
|
||||
}
|
||||
else if (buildVersion >= 14393)
|
||||
{
|
||||
m_WindowsVersion = WINDOWS_10_RS1;
|
||||
}
|
||||
else if (buildVersion >= 10586)
|
||||
{
|
||||
m_WindowsVersion = WINDOWS_10_TH2;
|
||||
}
|
||||
else if (buildVersion >= 10240)
|
||||
{
|
||||
m_WindowsVersion = WINDOWS_10;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_WindowsVersion = WINDOWS_10;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
m_WindowsVersion = WINDOWS_NEW;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
FORCEINLINE
|
||||
NTSTATUS MemoryCheck::PhGetProcessIsWow64(_In_ HANDLE ProcessHandle, _Out_ PBOOLEAN IsWow64Process)
|
||||
{
|
||||
NTSTATUS status;
|
||||
ULONG_PTR wow64;
|
||||
status = NtQueryInformationProcess(
|
||||
ProcessHandle,
|
||||
ProcessWow64Information,
|
||||
&wow64,
|
||||
sizeof(ULONG_PTR),
|
||||
NULL
|
||||
);
|
||||
|
||||
if (NT_SUCCESS(status))
|
||||
{
|
||||
*IsWow64Process = !!wow64;
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
BOOLEAN MemoryCheck::PhIsExecutingInWow64(VOID)
|
||||
{
|
||||
#ifndef _WIN64
|
||||
static volatile BOOLEAN valid = FALSE;
|
||||
static BOOLEAN isWow64 = FALSE;
|
||||
|
||||
if (!ReadBooleanAcquire(&valid))
|
||||
{
|
||||
PhGetProcessIsWow64(NtCurrentProcess(), &isWow64);
|
||||
WriteBooleanRelease(&valid, TRUE);
|
||||
}
|
||||
return isWow64;
|
||||
#else
|
||||
return FALSE;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
|
||||
string MemoryCheck::GetAppPath() {
|
||||
char szFilePath[MAX_PATH + 1] = { 0 };
|
||||
GetModuleFileName(NULL, szFilePath, MAX_PATH);
|
||||
(strrchr(szFilePath, '\\'))[1] = 0;
|
||||
return string(szFilePath);
|
||||
}
|
||||
740
src/MemoryCheck.h
Normal file
740
src/MemoryCheck.h
Normal file
@ -0,0 +1,740 @@
|
||||
#pragma once
|
||||
#include <windows.h>
|
||||
#include <psapi.h>
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
#include <atomic>
|
||||
#include <vector>
|
||||
#include <thread>
|
||||
#include "Config.h"
|
||||
|
||||
#include "MemDefine.h"
|
||||
|
||||
|
||||
using namespace std;
|
||||
typedef enum _SYSTEM_INFORMATION_CLASS
|
||||
{
|
||||
SystemBasicInformation, // q: SYSTEM_BASIC_INFORMATION
|
||||
SystemProcessorInformation, // q: SYSTEM_PROCESSOR_INFORMATION
|
||||
SystemPerformanceInformation, // q: SYSTEM_PERFORMANCE_INFORMATION
|
||||
SystemTimeOfDayInformation, // q: SYSTEM_TIMEOFDAY_INFORMATION
|
||||
SystemPathInformation, // not implemented
|
||||
SystemProcessInformation, // q: SYSTEM_PROCESS_INFORMATION
|
||||
SystemCallCountInformation, // q: SYSTEM_CALL_COUNT_INFORMATION
|
||||
SystemDeviceInformation, // q: SYSTEM_DEVICE_INFORMATION
|
||||
SystemProcessorPerformanceInformation, // q: SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION (EX in: USHORT ProcessorGroup)
|
||||
SystemFlagsInformation, // q: SYSTEM_FLAGS_INFORMATION
|
||||
SystemCallTimeInformation, // not implemented // SYSTEM_CALL_TIME_INFORMATION // 10
|
||||
SystemModuleInformation, // q: RTL_PROCESS_MODULES
|
||||
SystemLocksInformation, // q: RTL_PROCESS_LOCKS
|
||||
SystemStackTraceInformation, // q: RTL_PROCESS_BACKTRACES
|
||||
SystemPagedPoolInformation, // not implemented
|
||||
SystemNonPagedPoolInformation, // not implemented
|
||||
SystemHandleInformation, // q: SYSTEM_HANDLE_INFORMATION
|
||||
SystemObjectInformation, // q: SYSTEM_OBJECTTYPE_INFORMATION mixed with SYSTEM_OBJECT_INFORMATION
|
||||
SystemPageFileInformation, // q: SYSTEM_PAGEFILE_INFORMATION
|
||||
SystemVdmInstemulInformation, // q: SYSTEM_VDM_INSTEMUL_INFO
|
||||
SystemVdmBopInformation, // not implemented // 20
|
||||
SystemFileCacheInformation, // q: SYSTEM_FILECACHE_INFORMATION; s (requires SeIncreaseQuotaPrivilege) (info for WorkingSetTypeSystemCache)
|
||||
SystemPoolTagInformation, // q: SYSTEM_POOLTAG_INFORMATION
|
||||
SystemInterruptInformation, // q: SYSTEM_INTERRUPT_INFORMATION (EX in: USHORT ProcessorGroup)
|
||||
SystemDpcBehaviorInformation, // q: SYSTEM_DPC_BEHAVIOR_INFORMATION; s: SYSTEM_DPC_BEHAVIOR_INFORMATION (requires SeLoadDriverPrivilege)
|
||||
SystemFullMemoryInformation, // not implemented // SYSTEM_MEMORY_USAGE_INFORMATION
|
||||
SystemLoadGdiDriverInformation, // s (kernel-mode only)
|
||||
SystemUnloadGdiDriverInformation, // s (kernel-mode only)
|
||||
SystemTimeAdjustmentInformation, // q: SYSTEM_QUERY_TIME_ADJUST_INFORMATION; s: SYSTEM_SET_TIME_ADJUST_INFORMATION (requires SeSystemtimePrivilege)
|
||||
SystemSummaryMemoryInformation, // not implemented // SYSTEM_MEMORY_USAGE_INFORMATION
|
||||
SystemMirrorMemoryInformation, // s (requires license value "Kernel-MemoryMirroringSupported") (requires SeShutdownPrivilege) // 30
|
||||
SystemPerformanceTraceInformation, // q; s: (type depends on EVENT_TRACE_INFORMATION_CLASS)
|
||||
SystemObsolete0, // not implemented
|
||||
SystemExceptionInformation, // q: SYSTEM_EXCEPTION_INFORMATION
|
||||
SystemCrashDumpStateInformation, // s: SYSTEM_CRASH_DUMP_STATE_INFORMATION (requires SeDebugPrivilege)
|
||||
SystemKernelDebuggerInformation, // q: SYSTEM_KERNEL_DEBUGGER_INFORMATION
|
||||
SystemContextSwitchInformation, // q: SYSTEM_CONTEXT_SWITCH_INFORMATION
|
||||
SystemRegistryQuotaInformation, // q: SYSTEM_REGISTRY_QUOTA_INFORMATION; s (requires SeIncreaseQuotaPrivilege)
|
||||
SystemExtendServiceTableInformation, // s (requires SeLoadDriverPrivilege) // loads win32k only
|
||||
SystemPrioritySeparation, // s (requires SeTcbPrivilege)
|
||||
SystemVerifierAddDriverInformation, // s: UNICODE_STRING (requires SeDebugPrivilege) // 40
|
||||
SystemVerifierRemoveDriverInformation, // s: UNICODE_STRING (requires SeDebugPrivilege)
|
||||
SystemProcessorIdleInformation, // q: SYSTEM_PROCESSOR_IDLE_INFORMATION (EX in: USHORT ProcessorGroup)
|
||||
SystemLegacyDriverInformation, // q: SYSTEM_LEGACY_DRIVER_INFORMATION
|
||||
SystemCurrentTimeZoneInformation, // q; s: RTL_TIME_ZONE_INFORMATION
|
||||
SystemLookasideInformation, // q: SYSTEM_LOOKASIDE_INFORMATION
|
||||
SystemTimeSlipNotification, // s: HANDLE (NtCreateEvent) (requires SeSystemtimePrivilege)
|
||||
SystemSessionCreate, // not implemented
|
||||
SystemSessionDetach, // not implemented
|
||||
SystemSessionInformation, // not implemented (SYSTEM_SESSION_INFORMATION)
|
||||
SystemRangeStartInformation, // q: SYSTEM_RANGE_START_INFORMATION // 50
|
||||
SystemVerifierInformation, // q: SYSTEM_VERIFIER_INFORMATION; s (requires SeDebugPrivilege)
|
||||
SystemVerifierThunkExtend, // s (kernel-mode only)
|
||||
SystemSessionProcessInformation, // q: SYSTEM_SESSION_PROCESS_INFORMATION
|
||||
SystemLoadGdiDriverInSystemSpace, // s: SYSTEM_GDI_DRIVER_INFORMATION (kernel-mode only) (same as SystemLoadGdiDriverInformation)
|
||||
SystemNumaProcessorMap, // q: SYSTEM_NUMA_INFORMATION
|
||||
SystemPrefetcherInformation, // q; s: PREFETCHER_INFORMATION // PfSnQueryPrefetcherInformation
|
||||
SystemExtendedProcessInformation, // q: SYSTEM_EXTENDED_PROCESS_INFORMATION
|
||||
SystemRecommendedSharedDataAlignment, // q: ULONG // KeGetRecommendedSharedDataAlignment
|
||||
SystemComPlusPackage, // q; s: ULONG
|
||||
SystemNumaAvailableMemory, // q: SYSTEM_NUMA_INFORMATION // 60
|
||||
SystemProcessorPowerInformation, // q: SYSTEM_PROCESSOR_POWER_INFORMATION (EX in: USHORT ProcessorGroup)
|
||||
SystemEmulationBasicInformation, // q: SYSTEM_BASIC_INFORMATION
|
||||
SystemEmulationProcessorInformation, // q: SYSTEM_PROCESSOR_INFORMATION
|
||||
SystemExtendedHandleInformation, // q: SYSTEM_HANDLE_INFORMATION_EX
|
||||
SystemLostDelayedWriteInformation, // q: ULONG
|
||||
SystemBigPoolInformation, // q: SYSTEM_BIGPOOL_INFORMATION
|
||||
SystemSessionPoolTagInformation, // q: SYSTEM_SESSION_POOLTAG_INFORMATION
|
||||
SystemSessionMappedViewInformation, // q: SYSTEM_SESSION_MAPPED_VIEW_INFORMATION
|
||||
SystemHotpatchInformation, // q; s: SYSTEM_HOTPATCH_CODE_INFORMATION
|
||||
SystemObjectSecurityMode, // q: ULONG // 70
|
||||
SystemWatchdogTimerHandler, // s: SYSTEM_WATCHDOG_HANDLER_INFORMATION // (kernel-mode only)
|
||||
SystemWatchdogTimerInformation, // q: SYSTEM_WATCHDOG_TIMER_INFORMATION // NtQuerySystemInformationEx // (kernel-mode only)
|
||||
SystemLogicalProcessorInformation, // q: SYSTEM_LOGICAL_PROCESSOR_INFORMATION (EX in: USHORT ProcessorGroup) // NtQuerySystemInformationEx
|
||||
SystemWow64SharedInformationObsolete, // not implemented
|
||||
SystemRegisterFirmwareTableInformationHandler, // s: SYSTEM_FIRMWARE_TABLE_HANDLER // (kernel-mode only)
|
||||
SystemFirmwareTableInformation, // SYSTEM_FIRMWARE_TABLE_INFORMATION
|
||||
SystemModuleInformationEx, // q: RTL_PROCESS_MODULE_INFORMATION_EX // since VISTA
|
||||
SystemVerifierTriageInformation, // not implemented
|
||||
SystemSuperfetchInformation, // q; s: SUPERFETCH_INFORMATION // PfQuerySuperfetchInformation
|
||||
SystemMemoryListInformation, // q: SYSTEM_MEMORY_LIST_INFORMATION; s: SYSTEM_MEMORY_LIST_COMMAND (requires SeProfileSingleProcessPrivilege) // 80
|
||||
SystemFileCacheInformationEx, // q: SYSTEM_FILECACHE_INFORMATION; s (requires SeIncreaseQuotaPrivilege) (same as SystemFileCacheInformation)
|
||||
SystemThreadPriorityClientIdInformation, // s: SYSTEM_THREAD_CID_PRIORITY_INFORMATION (requires SeIncreaseBasePriorityPrivilege) // NtQuerySystemInformationEx
|
||||
SystemProcessorIdleCycleTimeInformation, // q: SYSTEM_PROCESSOR_IDLE_CYCLE_TIME_INFORMATION[] (EX in: USHORT ProcessorGroup) // NtQuerySystemInformationEx
|
||||
SystemVerifierCancellationInformation, // SYSTEM_VERIFIER_CANCELLATION_INFORMATION // name:wow64:whNT32QuerySystemVerifierCancellationInformation
|
||||
SystemProcessorPowerInformationEx, // not implemented
|
||||
SystemRefTraceInformation, // q; s: SYSTEM_REF_TRACE_INFORMATION // ObQueryRefTraceInformation
|
||||
SystemSpecialPoolInformation, // q; s: SYSTEM_SPECIAL_POOL_INFORMATION (requires SeDebugPrivilege) // MmSpecialPoolTag, then MmSpecialPoolCatchOverruns != 0
|
||||
SystemProcessIdInformation, // q: SYSTEM_PROCESS_ID_INFORMATION
|
||||
SystemErrorPortInformation, // s (requires SeTcbPrivilege)
|
||||
SystemBootEnvironmentInformation, // q: SYSTEM_BOOT_ENVIRONMENT_INFORMATION // 90
|
||||
SystemHypervisorInformation, // q: SYSTEM_HYPERVISOR_QUERY_INFORMATION
|
||||
SystemVerifierInformationEx, // q; s: SYSTEM_VERIFIER_INFORMATION_EX
|
||||
SystemTimeZoneInformation, // q; s: RTL_TIME_ZONE_INFORMATION (requires SeTimeZonePrivilege)
|
||||
SystemImageFileExecutionOptionsInformation, // s: SYSTEM_IMAGE_FILE_EXECUTION_OPTIONS_INFORMATION (requires SeTcbPrivilege)
|
||||
SystemCoverageInformation, // q: COVERAGE_MODULES s: COVERAGE_MODULE_REQUEST // ExpCovQueryInformation (requires SeDebugPrivilege)
|
||||
SystemPrefetchPatchInformation, // SYSTEM_PREFETCH_PATCH_INFORMATION
|
||||
SystemVerifierFaultsInformation, // s: SYSTEM_VERIFIER_FAULTS_INFORMATION (requires SeDebugPrivilege)
|
||||
SystemSystemPartitionInformation, // q: SYSTEM_SYSTEM_PARTITION_INFORMATION
|
||||
SystemSystemDiskInformation, // q: SYSTEM_SYSTEM_DISK_INFORMATION
|
||||
SystemProcessorPerformanceDistribution, // q: SYSTEM_PROCESSOR_PERFORMANCE_DISTRIBUTION (EX in: USHORT ProcessorGroup) // NtQuerySystemInformationEx // 100
|
||||
SystemNumaProximityNodeInformation, // q; s: SYSTEM_NUMA_PROXIMITY_MAP
|
||||
SystemDynamicTimeZoneInformation, // q; s: RTL_DYNAMIC_TIME_ZONE_INFORMATION (requires SeTimeZonePrivilege)
|
||||
SystemCodeIntegrityInformation, // q: SYSTEM_CODEINTEGRITY_INFORMATION // SeCodeIntegrityQueryInformation
|
||||
SystemProcessorMicrocodeUpdateInformation, // s: SYSTEM_PROCESSOR_MICROCODE_UPDATE_INFORMATION
|
||||
SystemProcessorBrandString, // q: CHAR[] // HaliQuerySystemInformation -> HalpGetProcessorBrandString, info class 23
|
||||
SystemVirtualAddressInformation, // q: SYSTEM_VA_LIST_INFORMATION[]; s: SYSTEM_VA_LIST_INFORMATION[] (requires SeIncreaseQuotaPrivilege) // MmQuerySystemVaInformation
|
||||
SystemLogicalProcessorAndGroupInformation, // q: SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX (EX in: LOGICAL_PROCESSOR_RELATIONSHIP RelationshipType) // since WIN7 // NtQuerySystemInformationEx // KeQueryLogicalProcessorRelationship
|
||||
SystemProcessorCycleTimeInformation, // q: SYSTEM_PROCESSOR_CYCLE_TIME_INFORMATION[] (EX in: USHORT ProcessorGroup) // NtQuerySystemInformationEx
|
||||
SystemStoreInformation, // q; s: SYSTEM_STORE_INFORMATION (requires SeProfileSingleProcessPrivilege) // SmQueryStoreInformation
|
||||
SystemRegistryAppendString, // s: SYSTEM_REGISTRY_APPEND_STRING_PARAMETERS // 110
|
||||
SystemAitSamplingValue, // s: ULONG (requires SeProfileSingleProcessPrivilege)
|
||||
SystemVhdBootInformation, // q: SYSTEM_VHD_BOOT_INFORMATION
|
||||
SystemCpuQuotaInformation, // q; s: PS_CPU_QUOTA_QUERY_INFORMATION
|
||||
SystemNativeBasicInformation, // q: SYSTEM_BASIC_INFORMATION
|
||||
SystemErrorPortTimeouts, // SYSTEM_ERROR_PORT_TIMEOUTS
|
||||
SystemLowPriorityIoInformation, // q: SYSTEM_LOW_PRIORITY_IO_INFORMATION
|
||||
SystemTpmBootEntropyInformation, // q: BOOT_ENTROPY_NT_RESULT // ExQueryBootEntropyInformation
|
||||
SystemVerifierCountersInformation, // q: SYSTEM_VERIFIER_COUNTERS_INFORMATION
|
||||
SystemPagedPoolInformationEx, // q: SYSTEM_FILECACHE_INFORMATION; s (requires SeIncreaseQuotaPrivilege) (info for WorkingSetTypePagedPool)
|
||||
SystemSystemPtesInformationEx, // q: SYSTEM_FILECACHE_INFORMATION; s (requires SeIncreaseQuotaPrivilege) (info for WorkingSetTypeSystemPtes) // 120
|
||||
SystemNodeDistanceInformation, // q: USHORT[4*NumaNodes] // (EX in: USHORT NodeNumber) // NtQuerySystemInformationEx
|
||||
SystemAcpiAuditInformation, // q: SYSTEM_ACPI_AUDIT_INFORMATION // HaliQuerySystemInformation -> HalpAuditQueryResults, info class 26
|
||||
SystemBasicPerformanceInformation, // q: SYSTEM_BASIC_PERFORMANCE_INFORMATION // name:wow64:whNtQuerySystemInformation_SystemBasicPerformanceInformation
|
||||
SystemQueryPerformanceCounterInformation, // q: SYSTEM_QUERY_PERFORMANCE_COUNTER_INFORMATION // since WIN7 SP1
|
||||
SystemSessionBigPoolInformation, // q: SYSTEM_SESSION_POOLTAG_INFORMATION // since WIN8
|
||||
SystemBootGraphicsInformation, // q; s: SYSTEM_BOOT_GRAPHICS_INFORMATION (kernel-mode only)
|
||||
SystemScrubPhysicalMemoryInformation, // q; s: MEMORY_SCRUB_INFORMATION
|
||||
SystemBadPageInformation, // SYSTEM_BAD_PAGE_INFORMATION
|
||||
SystemProcessorProfileControlArea, // q; s: SYSTEM_PROCESSOR_PROFILE_CONTROL_AREA
|
||||
SystemCombinePhysicalMemoryInformation, // s: MEMORY_COMBINE_INFORMATION, MEMORY_COMBINE_INFORMATION_EX, MEMORY_COMBINE_INFORMATION_EX2 // 130
|
||||
SystemEntropyInterruptTimingInformation, // q; s: SYSTEM_ENTROPY_TIMING_INFORMATION
|
||||
SystemConsoleInformation, // q; s: SYSTEM_CONSOLE_INFORMATION
|
||||
SystemPlatformBinaryInformation, // q: SYSTEM_PLATFORM_BINARY_INFORMATION (requires SeTcbPrivilege)
|
||||
SystemPolicyInformation, // q: SYSTEM_POLICY_INFORMATION (Warbird/Encrypt/Decrypt/Execute)
|
||||
SystemHypervisorProcessorCountInformation, // q: SYSTEM_HYPERVISOR_PROCESSOR_COUNT_INFORMATION
|
||||
SystemDeviceDataInformation, // q: SYSTEM_DEVICE_DATA_INFORMATION
|
||||
SystemDeviceDataEnumerationInformation, // q: SYSTEM_DEVICE_DATA_INFORMATION
|
||||
SystemMemoryTopologyInformation, // q: SYSTEM_MEMORY_TOPOLOGY_INFORMATION
|
||||
SystemMemoryChannelInformation, // q: SYSTEM_MEMORY_CHANNEL_INFORMATION
|
||||
SystemBootLogoInformation, // q: SYSTEM_BOOT_LOGO_INFORMATION // 140
|
||||
SystemProcessorPerformanceInformationEx, // q: SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION_EX // (EX in: USHORT ProcessorGroup) // NtQuerySystemInformationEx // since WINBLUE
|
||||
SystemCriticalProcessErrorLogInformation, // CRITICAL_PROCESS_EXCEPTION_DATA
|
||||
SystemSecureBootPolicyInformation, // q: SYSTEM_SECUREBOOT_POLICY_INFORMATION
|
||||
SystemPageFileInformationEx, // q: SYSTEM_PAGEFILE_INFORMATION_EX
|
||||
SystemSecureBootInformation, // q: SYSTEM_SECUREBOOT_INFORMATION
|
||||
SystemEntropyInterruptTimingRawInformation, // q; s: SYSTEM_ENTROPY_TIMING_INFORMATION
|
||||
SystemPortableWorkspaceEfiLauncherInformation, // q: SYSTEM_PORTABLE_WORKSPACE_EFI_LAUNCHER_INFORMATION
|
||||
SystemFullProcessInformation, // q: SYSTEM_EXTENDED_PROCESS_INFORMATION with SYSTEM_PROCESS_INFORMATION_EXTENSION (requires admin)
|
||||
SystemKernelDebuggerInformationEx, // q: SYSTEM_KERNEL_DEBUGGER_INFORMATION_EX
|
||||
SystemBootMetadataInformation, // 150 // (requires SeTcbPrivilege)
|
||||
SystemSoftRebootInformation, // q: ULONG
|
||||
SystemElamCertificateInformation, // s: SYSTEM_ELAM_CERTIFICATE_INFORMATION
|
||||
SystemOfflineDumpConfigInformation, // q: OFFLINE_CRASHDUMP_CONFIGURATION_TABLE_V2
|
||||
SystemProcessorFeaturesInformation, // q: SYSTEM_PROCESSOR_FEATURES_INFORMATION
|
||||
SystemRegistryReconciliationInformation, // s: NULL (requires admin) (flushes registry hives)
|
||||
SystemEdidInformation, // q: SYSTEM_EDID_INFORMATION
|
||||
SystemManufacturingInformation, // q: SYSTEM_MANUFACTURING_INFORMATION // since THRESHOLD
|
||||
SystemEnergyEstimationConfigInformation, // q: SYSTEM_ENERGY_ESTIMATION_CONFIG_INFORMATION
|
||||
SystemHypervisorDetailInformation, // q: SYSTEM_HYPERVISOR_DETAIL_INFORMATION
|
||||
SystemProcessorCycleStatsInformation, // q: SYSTEM_PROCESSOR_CYCLE_STATS_INFORMATION (EX in: USHORT ProcessorGroup) // NtQuerySystemInformationEx // 160
|
||||
SystemVmGenerationCountInformation,
|
||||
SystemTrustedPlatformModuleInformation, // q: SYSTEM_TPM_INFORMATION
|
||||
SystemKernelDebuggerFlags, // SYSTEM_KERNEL_DEBUGGER_FLAGS
|
||||
SystemCodeIntegrityPolicyInformation, // q; s: SYSTEM_CODEINTEGRITYPOLICY_INFORMATION
|
||||
SystemIsolatedUserModeInformation, // q: SYSTEM_ISOLATED_USER_MODE_INFORMATION
|
||||
SystemHardwareSecurityTestInterfaceResultsInformation,
|
||||
SystemSingleModuleInformation, // q: SYSTEM_SINGLE_MODULE_INFORMATION
|
||||
SystemAllowedCpuSetsInformation, // s: SYSTEM_WORKLOAD_ALLOWED_CPU_SET_INFORMATION
|
||||
SystemVsmProtectionInformation, // q: SYSTEM_VSM_PROTECTION_INFORMATION (previously SystemDmaProtectionInformation)
|
||||
SystemInterruptCpuSetsInformation, // q: SYSTEM_INTERRUPT_CPU_SET_INFORMATION // 170
|
||||
SystemSecureBootPolicyFullInformation, // q: SYSTEM_SECUREBOOT_POLICY_FULL_INFORMATION
|
||||
SystemCodeIntegrityPolicyFullInformation,
|
||||
SystemAffinitizedInterruptProcessorInformation, // q: KAFFINITY_EX // (requires SeIncreaseBasePriorityPrivilege)
|
||||
SystemRootSiloInformation, // q: SYSTEM_ROOT_SILO_INFORMATION
|
||||
SystemCpuSetInformation, // q: SYSTEM_CPU_SET_INFORMATION // since THRESHOLD2
|
||||
SystemCpuSetTagInformation, // q: SYSTEM_CPU_SET_TAG_INFORMATION
|
||||
SystemWin32WerStartCallout,
|
||||
SystemSecureKernelProfileInformation, // q: SYSTEM_SECURE_KERNEL_HYPERGUARD_PROFILE_INFORMATION
|
||||
SystemCodeIntegrityPlatformManifestInformation, // q: SYSTEM_SECUREBOOT_PLATFORM_MANIFEST_INFORMATION // NtQuerySystemInformationEx // since REDSTONE
|
||||
SystemInterruptSteeringInformation, // q: in: SYSTEM_INTERRUPT_STEERING_INFORMATION_INPUT, out: SYSTEM_INTERRUPT_STEERING_INFORMATION_OUTPUT // NtQuerySystemInformationEx // 180
|
||||
SystemSupportedProcessorArchitectures, // p: in opt: HANDLE, out: SYSTEM_SUPPORTED_PROCESSOR_ARCHITECTURES_INFORMATION[] // NtQuerySystemInformationEx
|
||||
SystemMemoryUsageInformation, // q: SYSTEM_MEMORY_USAGE_INFORMATION
|
||||
SystemCodeIntegrityCertificateInformation, // q: SYSTEM_CODEINTEGRITY_CERTIFICATE_INFORMATION
|
||||
SystemPhysicalMemoryInformation, // q: SYSTEM_PHYSICAL_MEMORY_INFORMATION // since REDSTONE2
|
||||
SystemControlFlowTransition, // (Warbird/Encrypt/Decrypt/Execute)
|
||||
SystemKernelDebuggingAllowed, // s: ULONG
|
||||
SystemActivityModerationExeState, // s: SYSTEM_ACTIVITY_MODERATION_EXE_STATE
|
||||
SystemActivityModerationUserSettings, // q: SYSTEM_ACTIVITY_MODERATION_USER_SETTINGS
|
||||
SystemCodeIntegrityPoliciesFullInformation, // NtQuerySystemInformationEx
|
||||
SystemCodeIntegrityUnlockInformation, // SYSTEM_CODEINTEGRITY_UNLOCK_INFORMATION // 190
|
||||
SystemIntegrityQuotaInformation,
|
||||
SystemFlushInformation, // q: SYSTEM_FLUSH_INFORMATION
|
||||
SystemProcessorIdleMaskInformation, // q: ULONG_PTR[ActiveGroupCount] // since REDSTONE3
|
||||
SystemSecureDumpEncryptionInformation, // NtQuerySystemInformationEx
|
||||
SystemWriteConstraintInformation, // SYSTEM_WRITE_CONSTRAINT_INFORMATION
|
||||
SystemKernelVaShadowInformation, // SYSTEM_KERNEL_VA_SHADOW_INFORMATION
|
||||
SystemHypervisorSharedPageInformation, // SYSTEM_HYPERVISOR_SHARED_PAGE_INFORMATION // since REDSTONE4
|
||||
SystemFirmwareBootPerformanceInformation,
|
||||
SystemCodeIntegrityVerificationInformation, // SYSTEM_CODEINTEGRITYVERIFICATION_INFORMATION
|
||||
SystemFirmwarePartitionInformation, // SYSTEM_FIRMWARE_PARTITION_INFORMATION // 200
|
||||
SystemSpeculationControlInformation, // SYSTEM_SPECULATION_CONTROL_INFORMATION // (CVE-2017-5715) REDSTONE3 and above.
|
||||
SystemDmaGuardPolicyInformation, // SYSTEM_DMA_GUARD_POLICY_INFORMATION
|
||||
SystemEnclaveLaunchControlInformation, // SYSTEM_ENCLAVE_LAUNCH_CONTROL_INFORMATION
|
||||
SystemWorkloadAllowedCpuSetsInformation, // SYSTEM_WORKLOAD_ALLOWED_CPU_SET_INFORMATION // since REDSTONE5
|
||||
SystemCodeIntegrityUnlockModeInformation, // SYSTEM_CODEINTEGRITY_UNLOCK_INFORMATION
|
||||
SystemLeapSecondInformation, // SYSTEM_LEAP_SECOND_INFORMATION
|
||||
SystemFlags2Information, // q: SYSTEM_FLAGS_INFORMATION
|
||||
SystemSecurityModelInformation, // SYSTEM_SECURITY_MODEL_INFORMATION // since 19H1
|
||||
SystemCodeIntegritySyntheticCacheInformation, // NtQuerySystemInformationEx
|
||||
SystemFeatureConfigurationInformation, // q: in: SYSTEM_FEATURE_CONFIGURATION_QUERY, out: SYSTEM_FEATURE_CONFIGURATION_INFORMATION; s: SYSTEM_FEATURE_CONFIGURATION_UPDATE // NtQuerySystemInformationEx // since 20H1 // 210
|
||||
SystemFeatureConfigurationSectionInformation, // q: in: SYSTEM_FEATURE_CONFIGURATION_SECTIONS_REQUEST, out: SYSTEM_FEATURE_CONFIGURATION_SECTIONS_INFORMATION // NtQuerySystemInformationEx
|
||||
SystemFeatureUsageSubscriptionInformation, // q: SYSTEM_FEATURE_USAGE_SUBSCRIPTION_DETAILS; s: SYSTEM_FEATURE_USAGE_SUBSCRIPTION_UPDATE
|
||||
SystemSecureSpeculationControlInformation, // SECURE_SPECULATION_CONTROL_INFORMATION
|
||||
SystemSpacesBootInformation, // since 20H2
|
||||
SystemFwRamdiskInformation, // SYSTEM_FIRMWARE_RAMDISK_INFORMATION
|
||||
SystemWheaIpmiHardwareInformation,
|
||||
SystemDifSetRuleClassInformation, // s: SYSTEM_DIF_VOLATILE_INFORMATION (requires SeDebugPrivilege)
|
||||
SystemDifClearRuleClassInformation, // s: NULL (requires SeDebugPrivilege)
|
||||
SystemDifApplyPluginVerificationOnDriver, // SYSTEM_DIF_PLUGIN_DRIVER_INFORMATION (requires SeDebugPrivilege)
|
||||
SystemDifRemovePluginVerificationOnDriver, // SYSTEM_DIF_PLUGIN_DRIVER_INFORMATION (requires SeDebugPrivilege) // 220
|
||||
SystemShadowStackInformation, // SYSTEM_SHADOW_STACK_INFORMATION
|
||||
SystemBuildVersionInformation, // q: in: ULONG (LayerNumber), out: SYSTEM_BUILD_VERSION_INFORMATION // NtQuerySystemInformationEx // 222
|
||||
SystemPoolLimitInformation, // SYSTEM_POOL_LIMIT_INFORMATION (requires SeIncreaseQuotaPrivilege) // NtQuerySystemInformationEx
|
||||
SystemCodeIntegrityAddDynamicStore, // CodeIntegrity-AllowConfigurablePolicy-CustomKernelSigners
|
||||
SystemCodeIntegrityClearDynamicStores, // CodeIntegrity-AllowConfigurablePolicy-CustomKernelSigners
|
||||
SystemDifPoolTrackingInformation,
|
||||
SystemPoolZeroingInformation, // q: SYSTEM_POOL_ZEROING_INFORMATION
|
||||
SystemDpcWatchdogInformation, // q; s: SYSTEM_DPC_WATCHDOG_CONFIGURATION_INFORMATION
|
||||
SystemDpcWatchdogInformation2, // q; s: SYSTEM_DPC_WATCHDOG_CONFIGURATION_INFORMATION_V2
|
||||
SystemSupportedProcessorArchitectures2, // q: in opt: HANDLE, out: SYSTEM_SUPPORTED_PROCESSOR_ARCHITECTURES_INFORMATION[] // NtQuerySystemInformationEx // 230
|
||||
SystemSingleProcessorRelationshipInformation, // q: SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX // (EX in: PROCESSOR_NUMBER Processor) // NtQuerySystemInformationEx
|
||||
SystemXfgCheckFailureInformation, // q: SYSTEM_XFG_FAILURE_INFORMATION
|
||||
SystemIommuStateInformation, // SYSTEM_IOMMU_STATE_INFORMATION // since 22H1
|
||||
SystemHypervisorMinrootInformation, // SYSTEM_HYPERVISOR_MINROOT_INFORMATION
|
||||
SystemHypervisorBootPagesInformation, // SYSTEM_HYPERVISOR_BOOT_PAGES_INFORMATION
|
||||
SystemPointerAuthInformation, // SYSTEM_POINTER_AUTH_INFORMATION
|
||||
SystemSecureKernelDebuggerInformation, // NtQuerySystemInformationEx
|
||||
SystemOriginalImageFeatureInformation, // q: in: SYSTEM_ORIGINAL_IMAGE_FEATURE_INFORMATION_INPUT, out: SYSTEM_ORIGINAL_IMAGE_FEATURE_INFORMATION_OUTPUT // NtQuerySystemInformationEx
|
||||
SystemMemoryNumaInformation, // SYSTEM_MEMORY_NUMA_INFORMATION_INPUT, SYSTEM_MEMORY_NUMA_INFORMATION_OUTPUT // NtQuerySystemInformationEx
|
||||
SystemMemoryNumaPerformanceInformation, // SYSTEM_MEMORY_NUMA_PERFORMANCE_INFORMATION_INPUTSYSTEM_MEMORY_NUMA_PERFORMANCE_INFORMATION_INPUT, SYSTEM_MEMORY_NUMA_PERFORMANCE_INFORMATION_OUTPUT // since 24H2 // 240
|
||||
SystemCodeIntegritySignedPoliciesFullInformation,
|
||||
SystemSecureCoreInformation, // SystemSecureSecretsInformation
|
||||
SystemTrustedAppsRuntimeInformation, // SYSTEM_TRUSTEDAPPS_RUNTIME_INFORMATION
|
||||
SystemBadPageInformationEx, // SYSTEM_BAD_PAGE_INFORMATION
|
||||
SystemResourceDeadlockTimeout, // ULONG
|
||||
SystemBreakOnContextUnwindFailureInformation, // ULONG (requires SeDebugPrivilege)
|
||||
SystemOslRamdiskInformation, // SYSTEM_OSL_RAMDISK_INFORMATION
|
||||
SystemCodeIntegrityPolicyManagementInformation, // since 25H2
|
||||
SystemMemoryNumaCacheInformation,
|
||||
SystemProcessorFeaturesBitMapInformation,
|
||||
MaxSystemInfoClass
|
||||
} SYSTEM_INFORMATION_CLASS;
|
||||
|
||||
|
||||
typedef struct _CLIENT_ID
|
||||
{
|
||||
HANDLE UniqueProcess;
|
||||
HANDLE UniqueThread;
|
||||
} CLIENT_ID, * PCLIENT_ID;
|
||||
|
||||
typedef LONG KPRIORITY, * PKPRIORITY;
|
||||
|
||||
typedef enum _KTHREAD_STATE
|
||||
{
|
||||
Initialized,
|
||||
Ready,
|
||||
Running,
|
||||
Standby,
|
||||
Terminated,
|
||||
Waiting,
|
||||
Transition,
|
||||
DeferredReady,
|
||||
GateWaitObsolete,
|
||||
WaitingForProcessInSwap,
|
||||
MaximumThreadState
|
||||
} KTHREAD_STATE, * PKTHREAD_STATE;
|
||||
|
||||
typedef enum _KWAIT_REASON
|
||||
{
|
||||
Executive, // Waiting for an executive event.
|
||||
FreePage, // Waiting for a free page.
|
||||
PageIn, // Waiting for a page to be read in.
|
||||
PoolAllocation, // Waiting for a pool allocation.
|
||||
DelayExecution, // Waiting due to a delay execution. // NtDelayExecution
|
||||
Suspended, // Waiting because the thread is suspended. // NtSuspendThread
|
||||
UserRequest, // Waiting due to a user request. // NtWaitForSingleObject
|
||||
WrExecutive, // Waiting for an executive event.
|
||||
WrFreePage, // Waiting for a free page.
|
||||
WrPageIn, // Waiting for a page to be read in.
|
||||
WrPoolAllocation, // Waiting for a pool allocation.
|
||||
WrDelayExecution, // Waiting due to a delay execution.
|
||||
WrSuspended, // Waiting because the thread is suspended.
|
||||
WrUserRequest, // Waiting due to a user request.
|
||||
WrEventPair, // Waiting for an event pair. // NtCreateEventPair
|
||||
WrQueue, // Waiting for a queue. // NtRemoveIoCompletion
|
||||
WrLpcReceive, // Waiting for an LPC receive. // NtReplyWaitReceivePort
|
||||
WrLpcReply, // Waiting for an LPC reply. // NtRequestWaitReplyPort
|
||||
WrVirtualMemory, // Waiting for virtual memory.
|
||||
WrPageOut, // Waiting for a page to be written out. // NtFlushVirtualMemory
|
||||
WrRendezvous, // Waiting for a rendezvous.
|
||||
WrKeyedEvent, // Waiting for a keyed event. // NtCreateKeyedEvent
|
||||
WrTerminated, // Waiting for thread termination.
|
||||
WrProcessInSwap, // Waiting for a process to be swapped in.
|
||||
WrCpuRateControl, // Waiting for CPU rate control.
|
||||
WrCalloutStack, // Waiting for a callout stack.
|
||||
WrKernel, // Waiting for a kernel event.
|
||||
WrResource, // Waiting for a resource.
|
||||
WrPushLock, // Waiting for a push lock.
|
||||
WrMutex, // Waiting for a mutex.
|
||||
WrQuantumEnd, // Waiting for the end of a quantum.
|
||||
WrDispatchInt, // Waiting for a dispatch interrupt.
|
||||
WrPreempted, // Waiting because the thread was preempted.
|
||||
WrYieldExecution, // Waiting to yield execution.
|
||||
WrFastMutex, // Waiting for a fast mutex.
|
||||
WrGuardedMutex, // Waiting for a guarded mutex.
|
||||
WrRundown, // Waiting for a rundown.
|
||||
WrAlertByThreadId, // Waiting for an alert by thread ID.
|
||||
WrDeferredPreempt, // Waiting for a deferred preemption.
|
||||
WrPhysicalFault, // Waiting for a physical fault.
|
||||
WrIoRing, // Waiting for an I/O ring.
|
||||
WrMdlCache, // Waiting for an MDL cache.
|
||||
WrRcu, // Waiting for read-copy-update (RCU) synchronization.
|
||||
MaximumWaitReason
|
||||
} KWAIT_REASON, * PKWAIT_REASON;
|
||||
|
||||
typedef struct _SYSTEM_THREAD_INFORMATION
|
||||
{
|
||||
LARGE_INTEGER KernelTime; // Number of 100-nanosecond intervals spent executing kernel code.
|
||||
LARGE_INTEGER UserTime; // Number of 100-nanosecond intervals spent executing user code.
|
||||
LARGE_INTEGER CreateTime; // The date and time when the thread was created.
|
||||
ULONG WaitTime; // The current time spent in ready queue or waiting (depending on the thread state).
|
||||
PVOID StartAddress; // The initial start address of the thread.
|
||||
CLIENT_ID ClientId; // The identifier of the thread and the process owning the thread.
|
||||
KPRIORITY Priority; // The dynamic priority of the thread.
|
||||
KPRIORITY BasePriority; // The starting priority of the thread.
|
||||
ULONG ContextSwitches; // The total number of context switches performed.
|
||||
KTHREAD_STATE ThreadState; // The current state of the thread.
|
||||
KWAIT_REASON WaitReason; // The current reason the thread is waiting.
|
||||
} SYSTEM_THREAD_INFORMATION, * PSYSTEM_THREAD_INFORMATION;
|
||||
|
||||
typedef struct _UNICODE_STRING
|
||||
{
|
||||
USHORT Length;
|
||||
USHORT MaximumLength;
|
||||
_Field_size_bytes_part_opt_(MaximumLength, Length) PWCH Buffer;
|
||||
} UNICODE_STRING, * PUNICODE_STRING;
|
||||
|
||||
typedef struct _SYSTEM_PROCESS_INFORMATION
|
||||
{
|
||||
ULONG NextEntryOffset; // The address of the previous item plus the value in the NextEntryOffset member. For the last item in the array, NextEntryOffset is 0.
|
||||
ULONG NumberOfThreads; // The NumberOfThreads member contains the number of threads in the process.
|
||||
ULONGLONG WorkingSetPrivateSize; // The total private memory that a process currently has allocated and is physically resident in memory. // since VISTA
|
||||
ULONG HardFaultCount; // The total number of hard faults for data from disk rather than from in-memory pages. // since WIN7
|
||||
ULONG NumberOfThreadsHighWatermark; // The peak number of threads that were running at any given point in time, indicative of potential performance bottlenecks related to thread management.
|
||||
ULONGLONG CycleTime; // The sum of the cycle time of all threads in the process.
|
||||
LARGE_INTEGER CreateTime; // Number of 100-nanosecond intervals since the creation time of the process. Not updated during system timezone changes.
|
||||
LARGE_INTEGER UserTime; // Number of 100-nanosecond intervals the process has executed in user mode.
|
||||
LARGE_INTEGER KernelTime; // Number of 100-nanosecond intervals the process has executed in kernel mode.
|
||||
UNICODE_STRING ImageName; // The file name of the executable image.
|
||||
KPRIORITY BasePriority; // The starting priority of the process.
|
||||
HANDLE UniqueProcessId; // The identifier of the process.
|
||||
HANDLE InheritedFromUniqueProcessId; // The identifier of the process that created this process. Not updated and incorrectly refers to processes with recycled identifiers.
|
||||
ULONG HandleCount; // The current number of open handles used by the process.
|
||||
ULONG SessionId; // The identifier of the Remote Desktop Services session under which the specified process is running.
|
||||
ULONG_PTR UniqueProcessKey; // since VISTA (requires SystemExtendedProcessInformation)
|
||||
SIZE_T PeakVirtualSize; // The peak size, in bytes, of the virtual memory used by the process.
|
||||
SIZE_T VirtualSize; // The current size, in bytes, of virtual memory used by the process.
|
||||
ULONG PageFaultCount; // The total number of page faults for data that is not currently in memory. The value wraps around to zero on average 24 hours.
|
||||
SIZE_T PeakWorkingSetSize; // The peak size, in kilobytes, of the working set of the process.
|
||||
SIZE_T WorkingSetSize; // The number of pages visible to the process in physical memory. These pages are resident and available for use without triggering a page fault.
|
||||
SIZE_T QuotaPeakPagedPoolUsage; // The peak quota charged to the process for pool usage, in bytes.
|
||||
SIZE_T QuotaPagedPoolUsage; // The quota charged to the process for paged pool usage, in bytes.
|
||||
SIZE_T QuotaPeakNonPagedPoolUsage; // The peak quota charged to the process for nonpaged pool usage, in bytes.
|
||||
SIZE_T QuotaNonPagedPoolUsage; // The current quota charged to the process for nonpaged pool usage.
|
||||
SIZE_T PagefileUsage; // The total number of bytes of page file storage in use by the process.
|
||||
SIZE_T PeakPagefileUsage; // The maximum number of bytes of page-file storage used by the process.
|
||||
SIZE_T PrivatePageCount; // The number of memory pages allocated for the use by the process.
|
||||
LARGE_INTEGER ReadOperationCount; // The total number of read operations performed.
|
||||
LARGE_INTEGER WriteOperationCount; // The total number of write operations performed.
|
||||
LARGE_INTEGER OtherOperationCount; // The total number of I/O operations performed other than read and write operations.
|
||||
LARGE_INTEGER ReadTransferCount; // The total number of bytes read during a read operation.
|
||||
LARGE_INTEGER WriteTransferCount; // The total number of bytes written during a write operation.
|
||||
LARGE_INTEGER OtherTransferCount; // The total number of bytes transferred during operations other than read and write operations.
|
||||
SYSTEM_THREAD_INFORMATION Threads[1]; // This type is not defined in the structure but was added for convenience.
|
||||
} SYSTEM_PROCESS_INFORMATION, * PSYSTEM_PROCESS_INFORMATION;
|
||||
|
||||
typedef struct _PROCESS_DISK_COUNTERS
|
||||
{
|
||||
ULONGLONG BytesRead;
|
||||
ULONGLONG BytesWritten;
|
||||
ULONGLONG ReadOperationCount;
|
||||
ULONGLONG WriteOperationCount;
|
||||
ULONGLONG FlushOperationCount;
|
||||
} PROCESS_DISK_COUNTERS, * PPROCESS_DISK_COUNTERS;
|
||||
|
||||
typedef union _ENERGY_STATE_DURATION
|
||||
{
|
||||
ULONGLONG Value;
|
||||
struct
|
||||
{
|
||||
ULONG LastChangeTime;
|
||||
ULONG Duration : 31;
|
||||
ULONG IsInState : 1;
|
||||
} DUMMYSTRUCTNAME;
|
||||
} ENERGY_STATE_DURATION, * PENERGY_STATE_DURATION;
|
||||
|
||||
typedef struct _PROCESS_ENERGY_VALUES
|
||||
{
|
||||
ULONGLONG Cycles[4][2];
|
||||
ULONGLONG DiskEnergy;
|
||||
ULONGLONG NetworkTailEnergy;
|
||||
ULONGLONG MBBTailEnergy;
|
||||
ULONGLONG NetworkTxRxBytes;
|
||||
ULONGLONG MBBTxRxBytes;
|
||||
union
|
||||
{
|
||||
ENERGY_STATE_DURATION Durations[3];
|
||||
struct
|
||||
{
|
||||
ENERGY_STATE_DURATION ForegroundDuration;
|
||||
ENERGY_STATE_DURATION DesktopVisibleDuration;
|
||||
ENERGY_STATE_DURATION PSMForegroundDuration;
|
||||
} DUMMYSTRUCTNAME;
|
||||
} DUMMYUNIONNAME;
|
||||
ULONG CompositionRendered;
|
||||
ULONG CompositionDirtyGenerated;
|
||||
ULONG CompositionDirtyPropagated;
|
||||
ULONG Reserved1;
|
||||
ULONGLONG AttributedCycles[4][2];
|
||||
ULONGLONG WorkOnBehalfCycles[4][2];
|
||||
} PROCESS_ENERGY_VALUES, * PPROCESS_ENERGY_VALUES;
|
||||
|
||||
typedef struct _SYSTEM_PROCESS_INFORMATION_EXTENSION
|
||||
{
|
||||
PROCESS_DISK_COUNTERS DiskCounters;
|
||||
ULONGLONG ContextSwitches;
|
||||
union
|
||||
{
|
||||
ULONG Flags;
|
||||
struct
|
||||
{
|
||||
ULONG HasStrongId : 1;
|
||||
ULONG Classification : 4; // SYSTEM_PROCESS_CLASSIFICATION
|
||||
ULONG BackgroundActivityModerated : 1;
|
||||
ULONG Spare : 26;
|
||||
} DUMMYSTRUCTNAME;
|
||||
} DUMMYUNIONNAME;
|
||||
ULONG UserSidOffset;
|
||||
ULONG PackageFullNameOffset; // since THRESHOLD
|
||||
PROCESS_ENERGY_VALUES EnergyValues; // since THRESHOLD
|
||||
ULONG AppIdOffset; // since THRESHOLD
|
||||
SIZE_T SharedCommitCharge; // since THRESHOLD2
|
||||
ULONG JobObjectId; // since REDSTONE
|
||||
ULONG SpareUlong; // since REDSTONE
|
||||
ULONGLONG ProcessSequenceNumber;
|
||||
} SYSTEM_PROCESS_INFORMATION_EXTENSION, * PSYSTEM_PROCESS_INFORMATION_EXTENSION;
|
||||
|
||||
typedef struct _RTL_OSVERSIONINFOEX
|
||||
{
|
||||
ULONG OSVersionInfoSize;
|
||||
ULONG MajorVersion;
|
||||
ULONG MinorVersion;
|
||||
ULONG BuildNumber;
|
||||
ULONG PlatformId;
|
||||
WCHAR CSDVersion[128];
|
||||
USHORT ServicePackMajor;
|
||||
USHORT ServicePackMinor;
|
||||
USHORT SuiteMask;
|
||||
UCHAR ProductType;
|
||||
UCHAR Reserved;
|
||||
} RTL_OSVERSIONINFOEX, * PRTL_OSVERSIONINFOEX;
|
||||
|
||||
#define WINDOWS_ANCIENT 0
|
||||
#define WINDOWS_XP 51 // August, 2001
|
||||
#define WINDOWS_SERVER_2003 52 // April, 2003
|
||||
#define WINDOWS_VISTA 60 // November, 2006
|
||||
#define WINDOWS_7 61 // July, 2009
|
||||
#define WINDOWS_8 62 // August, 2012
|
||||
#define WINDOWS_8_1 63 // August, 2013
|
||||
#define WINDOWS_10 100 // July, 2015 // Version 1507, Build 10240
|
||||
#define WINDOWS_10_TH2 101 // November, 2015 // Version 1511, Build 10586
|
||||
#define WINDOWS_10_RS1 102 // August, 2016 // Version 1607, Build 14393
|
||||
#define WINDOWS_10_RS2 103 // April, 2017 // Version 1703, Build 15063
|
||||
#define WINDOWS_10_RS3 104 // October, 2017 // Version 1709, Build 16299
|
||||
#define WINDOWS_10_RS4 105 // April, 2018 // Version 1803, Build 17134
|
||||
#define WINDOWS_10_RS5 106 // November, 2018 // Version 1809, Build 17763
|
||||
#define WINDOWS_10_19H1 107 // May, 2019 // Version 1903, Build 18362
|
||||
#define WINDOWS_10_19H2 108 // November, 2019 // Version 1909, Build 18363
|
||||
#define WINDOWS_10_20H1 109 // May, 2020 // Version 2004, Build 19041
|
||||
#define WINDOWS_10_20H2 110 // October, 2020 // Build 19042
|
||||
#define WINDOWS_10_21H1 111 // May, 2021 // Build 19043
|
||||
#define WINDOWS_10_21H2 112 // November, 2021 // Build 19044
|
||||
#define WINDOWS_10_22H2 113 // October, 2022 // Build 19045
|
||||
#define WINDOWS_11 114 // October, 2021 // Build 22000
|
||||
#define WINDOWS_11_22H2 115 // September, 2022 // Build 22621
|
||||
#define WINDOWS_11_23H2 116 // October, 2023 // Build 22631
|
||||
#define WINDOWS_11_24H2 117 // October, 2024 // Build 26100
|
||||
#define WINDOWS_MAX WINDOWS_11_24H2
|
||||
#define WINDOWS_NEW ULONG_MAX
|
||||
|
||||
#define NtCurrentProcess() ((HANDLE)(LONG_PTR)-1)
|
||||
|
||||
typedef enum _PROCESSINFOCLASS
|
||||
{
|
||||
ProcessBasicInformation, // q: PROCESS_BASIC_INFORMATION, PROCESS_EXTENDED_BASIC_INFORMATION
|
||||
ProcessQuotaLimits, // qs: QUOTA_LIMITS, QUOTA_LIMITS_EX
|
||||
ProcessIoCounters, // q: IO_COUNTERS
|
||||
ProcessVmCounters, // q: VM_COUNTERS, VM_COUNTERS_EX, VM_COUNTERS_EX2
|
||||
ProcessTimes, // q: KERNEL_USER_TIMES
|
||||
ProcessBasePriority, // s: KPRIORITY
|
||||
ProcessRaisePriority, // s: ULONG
|
||||
ProcessDebugPort, // q: HANDLE
|
||||
ProcessExceptionPort, // s: PROCESS_EXCEPTION_PORT (requires SeTcbPrivilege)
|
||||
ProcessAccessToken, // s: PROCESS_ACCESS_TOKEN
|
||||
ProcessLdtInformation, // qs: PROCESS_LDT_INFORMATION // 10
|
||||
ProcessLdtSize, // s: PROCESS_LDT_SIZE
|
||||
ProcessDefaultHardErrorMode, // qs: ULONG
|
||||
ProcessIoPortHandlers, // s: PROCESS_IO_PORT_HANDLER_INFORMATION // (kernel-mode only)
|
||||
ProcessPooledUsageAndLimits, // q: POOLED_USAGE_AND_LIMITS
|
||||
ProcessWorkingSetWatch, // q: PROCESS_WS_WATCH_INFORMATION[]; s: void
|
||||
ProcessUserModeIOPL, // qs: ULONG (requires SeTcbPrivilege)
|
||||
ProcessEnableAlignmentFaultFixup, // s: BOOLEAN
|
||||
ProcessPriorityClass, // qs: PROCESS_PRIORITY_CLASS
|
||||
ProcessWx86Information, // qs: ULONG (requires SeTcbPrivilege) (VdmAllowed)
|
||||
ProcessHandleCount, // q: ULONG, PROCESS_HANDLE_INFORMATION // 20
|
||||
ProcessAffinityMask, // (q >WIN7)s: KAFFINITY, qs: GROUP_AFFINITY
|
||||
ProcessPriorityBoost, // qs: ULONG
|
||||
ProcessDeviceMap, // qs: PROCESS_DEVICEMAP_INFORMATION, PROCESS_DEVICEMAP_INFORMATION_EX
|
||||
ProcessSessionInformation, // q: PROCESS_SESSION_INFORMATION
|
||||
ProcessForegroundInformation, // s: PROCESS_FOREGROUND_BACKGROUND
|
||||
ProcessWow64Information, // q: ULONG_PTR
|
||||
ProcessImageFileName, // q: UNICODE_STRING
|
||||
ProcessLUIDDeviceMapsEnabled, // q: ULONG
|
||||
ProcessBreakOnTermination, // qs: ULONG
|
||||
ProcessDebugObjectHandle, // q: HANDLE // 30
|
||||
ProcessDebugFlags, // qs: ULONG
|
||||
ProcessHandleTracing, // q: PROCESS_HANDLE_TRACING_QUERY; s: PROCESS_HANDLE_TRACING_ENABLE[_EX] or void to disable
|
||||
ProcessIoPriority, // qs: IO_PRIORITY_HINT
|
||||
ProcessExecuteFlags, // qs: ULONG (MEM_EXECUTE_OPTION_*)
|
||||
ProcessTlsInformation, // PROCESS_TLS_INFORMATION // ProcessResourceManagement
|
||||
ProcessCookie, // q: ULONG
|
||||
ProcessImageInformation, // q: SECTION_IMAGE_INFORMATION
|
||||
ProcessCycleTime, // q: PROCESS_CYCLE_TIME_INFORMATION // since VISTA
|
||||
ProcessPagePriority, // qs: PAGE_PRIORITY_INFORMATION
|
||||
ProcessInstrumentationCallback, // s: PVOID or PROCESS_INSTRUMENTATION_CALLBACK_INFORMATION // 40
|
||||
ProcessThreadStackAllocation, // s: PROCESS_STACK_ALLOCATION_INFORMATION, PROCESS_STACK_ALLOCATION_INFORMATION_EX
|
||||
ProcessWorkingSetWatchEx, // q: PROCESS_WS_WATCH_INFORMATION_EX[]; s: void
|
||||
ProcessImageFileNameWin32, // q: UNICODE_STRING
|
||||
ProcessImageFileMapping, // q: HANDLE (input)
|
||||
ProcessAffinityUpdateMode, // qs: PROCESS_AFFINITY_UPDATE_MODE
|
||||
ProcessMemoryAllocationMode, // qs: PROCESS_MEMORY_ALLOCATION_MODE
|
||||
ProcessGroupInformation, // q: USHORT[]
|
||||
ProcessTokenVirtualizationEnabled, // s: ULONG
|
||||
ProcessConsoleHostProcess, // qs: ULONG_PTR // ProcessOwnerInformation
|
||||
ProcessWindowInformation, // q: PROCESS_WINDOW_INFORMATION // 50
|
||||
ProcessHandleInformation, // q: PROCESS_HANDLE_SNAPSHOT_INFORMATION // since WIN8
|
||||
ProcessMitigationPolicy, // s: PROCESS_MITIGATION_POLICY_INFORMATION
|
||||
ProcessDynamicFunctionTableInformation, // s: PROCESS_DYNAMIC_FUNCTION_TABLE_INFORMATION
|
||||
ProcessHandleCheckingMode, // qs: ULONG; s: 0 disables, otherwise enables
|
||||
ProcessKeepAliveCount, // q: PROCESS_KEEPALIVE_COUNT_INFORMATION
|
||||
ProcessRevokeFileHandles, // s: PROCESS_REVOKE_FILE_HANDLES_INFORMATION
|
||||
ProcessWorkingSetControl, // s: PROCESS_WORKING_SET_CONTROL
|
||||
ProcessHandleTable, // q: ULONG[] // since WINBLUE
|
||||
ProcessCheckStackExtentsMode, // qs: ULONG // KPROCESS->CheckStackExtents (CFG)
|
||||
ProcessCommandLineInformation, // q: UNICODE_STRING // 60
|
||||
ProcessProtectionInformation, // q: PS_PROTECTION
|
||||
ProcessMemoryExhaustion, // s: PROCESS_MEMORY_EXHAUSTION_INFO // since THRESHOLD
|
||||
ProcessFaultInformation, // s: PROCESS_FAULT_INFORMATION
|
||||
ProcessTelemetryIdInformation, // q: PROCESS_TELEMETRY_ID_INFORMATION
|
||||
ProcessCommitReleaseInformation, // qs: PROCESS_COMMIT_RELEASE_INFORMATION
|
||||
ProcessDefaultCpuSetsInformation, // qs: SYSTEM_CPU_SET_INFORMATION[5]
|
||||
ProcessAllowedCpuSetsInformation, // qs: SYSTEM_CPU_SET_INFORMATION[5]
|
||||
ProcessSubsystemProcess, // s: void // EPROCESS->SubsystemProcess
|
||||
ProcessJobMemoryInformation, // q: PROCESS_JOB_MEMORY_INFO
|
||||
ProcessInPrivate, // q: BOOLEAN; s: void // ETW // since THRESHOLD2 // 70
|
||||
ProcessRaiseUMExceptionOnInvalidHandleClose, // qs: ULONG; s: 0 disables, otherwise enables
|
||||
ProcessIumChallengeResponse,
|
||||
ProcessChildProcessInformation, // q: PROCESS_CHILD_PROCESS_INFORMATION
|
||||
ProcessHighGraphicsPriorityInformation, // qs: BOOLEAN (requires SeTcbPrivilege)
|
||||
ProcessSubsystemInformation, // q: SUBSYSTEM_INFORMATION_TYPE // since REDSTONE2
|
||||
ProcessEnergyValues, // q: PROCESS_ENERGY_VALUES, PROCESS_EXTENDED_ENERGY_VALUES
|
||||
ProcessPowerThrottlingState, // qs: POWER_THROTTLING_PROCESS_STATE
|
||||
ProcessReserved3Information, // ProcessActivityThrottlePolicy // PROCESS_ACTIVITY_THROTTLE_POLICY
|
||||
ProcessWin32kSyscallFilterInformation, // q: WIN32K_SYSCALL_FILTER
|
||||
ProcessDisableSystemAllowedCpuSets, // s: BOOLEAN // 80
|
||||
ProcessWakeInformation, // q: PROCESS_WAKE_INFORMATION
|
||||
ProcessEnergyTrackingState, // qs: PROCESS_ENERGY_TRACKING_STATE
|
||||
ProcessManageWritesToExecutableMemory, // MANAGE_WRITES_TO_EXECUTABLE_MEMORY // since REDSTONE3
|
||||
ProcessCaptureTrustletLiveDump, // q: ULONG
|
||||
ProcessTelemetryCoverage, // q: TELEMETRY_COVERAGE_HEADER; s: TELEMETRY_COVERAGE_POINT
|
||||
ProcessEnclaveInformation,
|
||||
ProcessEnableReadWriteVmLogging, // qs: PROCESS_READWRITEVM_LOGGING_INFORMATION
|
||||
ProcessUptimeInformation, // q: PROCESS_UPTIME_INFORMATION
|
||||
ProcessImageSection, // q: HANDLE
|
||||
ProcessDebugAuthInformation, // s: CiTool.exe --device-id // PplDebugAuthorization // since RS4 // 90
|
||||
ProcessSystemResourceManagement, // s: PROCESS_SYSTEM_RESOURCE_MANAGEMENT
|
||||
ProcessSequenceNumber, // q: ULONGLONG
|
||||
ProcessLoaderDetour, // since RS5
|
||||
ProcessSecurityDomainInformation, // q: PROCESS_SECURITY_DOMAIN_INFORMATION
|
||||
ProcessCombineSecurityDomainsInformation, // s: PROCESS_COMBINE_SECURITY_DOMAINS_INFORMATION
|
||||
ProcessEnableLogging, // qs: PROCESS_LOGGING_INFORMATION
|
||||
ProcessLeapSecondInformation, // qs: PROCESS_LEAP_SECOND_INFORMATION
|
||||
ProcessFiberShadowStackAllocation, // s: PROCESS_FIBER_SHADOW_STACK_ALLOCATION_INFORMATION // since 19H1
|
||||
ProcessFreeFiberShadowStackAllocation, // s: PROCESS_FREE_FIBER_SHADOW_STACK_ALLOCATION_INFORMATION
|
||||
ProcessAltSystemCallInformation, // s: PROCESS_SYSCALL_PROVIDER_INFORMATION // since 20H1 // 100
|
||||
ProcessDynamicEHContinuationTargets, // s: PROCESS_DYNAMIC_EH_CONTINUATION_TARGETS_INFORMATION
|
||||
ProcessDynamicEnforcedCetCompatibleRanges, // s: PROCESS_DYNAMIC_ENFORCED_ADDRESS_RANGE_INFORMATION // since 20H2
|
||||
ProcessCreateStateChange, // since WIN11
|
||||
ProcessApplyStateChange,
|
||||
ProcessEnableOptionalXStateFeatures, // s: ULONG64 // optional XState feature bitmask
|
||||
ProcessAltPrefetchParam, // qs: OVERRIDE_PREFETCH_PARAMETER // App Launch Prefetch (ALPF) // since 22H1
|
||||
ProcessAssignCpuPartitions, // HANDLE
|
||||
ProcessPriorityClassEx, // s: PROCESS_PRIORITY_CLASS_EX
|
||||
ProcessMembershipInformation, // q: PROCESS_MEMBERSHIP_INFORMATION
|
||||
ProcessEffectiveIoPriority, // q: IO_PRIORITY_HINT // 110
|
||||
ProcessEffectivePagePriority, // q: ULONG
|
||||
ProcessSchedulerSharedData, // SCHEDULER_SHARED_DATA_SLOT_INFORMATION // since 24H2
|
||||
ProcessSlistRollbackInformation,
|
||||
ProcessNetworkIoCounters, // q: PROCESS_NETWORK_COUNTERS
|
||||
ProcessFindFirstThreadByTebValue, // PROCESS_TEB_VALUE_INFORMATION
|
||||
ProcessEnclaveAddressSpaceRestriction, // since 25H2
|
||||
ProcessAvailableCpus, // PROCESS_AVAILABLE_CPUS_INFORMATION
|
||||
MaxProcessInfoClass
|
||||
} PROCESSINFOCLASS;
|
||||
|
||||
|
||||
|
||||
typedef _Return_type_success_(return >= 0) LONG NTSTATUS;
|
||||
typedef NTSTATUS* PNTSTATUS;
|
||||
#define NT_SUCCESS(Status) (((NTSTATUS)(Status)) >= 0)
|
||||
#define PH_FIRST_PROCESS(Processes) ((PSYSTEM_PROCESS_INFORMATION)(Processes))
|
||||
#define PTR_ADD_OFFSET(Pointer, Offset) ((PVOID)((ULONG_PTR)(Pointer) + (ULONG_PTR)(Offset)))
|
||||
#define PH_NEXT_PROCESS(Process) ( \
|
||||
((PSYSTEM_PROCESS_INFORMATION)(Process))->NextEntryOffset ? \
|
||||
(PSYSTEM_PROCESS_INFORMATION)PTR_ADD_OFFSET((Process), \
|
||||
((PSYSTEM_PROCESS_INFORMATION)(Process))->NextEntryOffset) : \
|
||||
NULL \
|
||||
)
|
||||
|
||||
|
||||
|
||||
#define STATUS_BUFFER_TOO_SMALL ((NTSTATUS)0xC0000023L)
|
||||
#define STATUS_INFO_LENGTH_MISMATCH ((NTSTATUS)0xC0000004L)
|
||||
//#define STATUS_NO_MEMORY ((NTSTATUS)0xC0000017L)
|
||||
|
||||
|
||||
#define PH_PROCESS_EXTENSION(Process) \
|
||||
((PSYSTEM_PROCESS_INFORMATION_EXTENSION)PTR_ADD_OFFSET((Process), \
|
||||
UFIELD_OFFSET(SYSTEM_PROCESS_INFORMATION, Threads) + \
|
||||
sizeof(SYSTEM_THREAD_INFORMATION) * \
|
||||
((PSYSTEM_PROCESS_INFORMATION)(Process))->NumberOfThreads))
|
||||
|
||||
|
||||
typedef NTSTATUS(NTAPI* PNTQUERYSYSTEMINFORMATION)(
|
||||
_In_ SYSTEM_INFORMATION_CLASS SystemInformationClass,
|
||||
_Out_writes_bytes_opt_(SystemInformationLength) PVOID SystemInformation,
|
||||
_In_ ULONG SystemInformationLength,
|
||||
_Out_opt_ PULONG ReturnLength
|
||||
);
|
||||
|
||||
typedef
|
||||
NTSTATUS
|
||||
(NTAPI* pNtQueryInformationProcess)
|
||||
(
|
||||
_In_ HANDLE ProcessHandle,
|
||||
_In_ PROCESSINFOCLASS ProcessInformationClass,
|
||||
_Out_writes_bytes_(ProcessInformationLength) PVOID ProcessInformation,
|
||||
_In_ ULONG ProcessInformationLength,
|
||||
_Out_opt_ PULONG ReturnLength
|
||||
);
|
||||
|
||||
class MemoryCheck
|
||||
{
|
||||
public:
|
||||
static MemoryCheck& GetInstance() {
|
||||
static MemoryCheck instance;
|
||||
return instance;
|
||||
}
|
||||
|
||||
void Init();
|
||||
void Start();
|
||||
void Stop();
|
||||
//void GetSystemMemoryUsage(MEMORYSTATUSEX& memStatus); // 返回0~100的百分比
|
||||
std::vector<MemoryCheckLog> GetTopProcesses(int topN = 5);
|
||||
std::vector<MemoryCheckLog> GetTopProcesses2(int topN = 5);
|
||||
MemoryCheck(const MemoryCheck&) = delete;
|
||||
MemoryCheck& operator=(const MemoryCheck&) = delete;
|
||||
|
||||
string GetAppPath();
|
||||
|
||||
private:
|
||||
MemoryCheck() :m_WindowsVersion(0xffffffffUL), m_UseSysApi(false), m_EnableProcessExtension(false), m_Config(nullptr){
|
||||
|
||||
}
|
||||
~MemoryCheck();
|
||||
|
||||
void MonitorProc();
|
||||
void CheckAndAlert();
|
||||
|
||||
MemoryCheckLog GetWinProcessInfo(DWORD pid);
|
||||
double SafeToDouble(const std::string& str);
|
||||
|
||||
NTSTATUS HbEnumProcesses(PVOID* Processes);
|
||||
|
||||
void InitializeWindowsInformation();
|
||||
BOOLEAN PhIsExecutingInWow64(VOID);
|
||||
FORCEINLINE NTSTATUS PhGetProcessIsWow64(_In_ HANDLE ProcessHandle, _Out_ PBOOLEAN IsWow64Process);
|
||||
private:
|
||||
std::atomic<bool> m_Running{ false };
|
||||
//std::thread m_MonitorThread;
|
||||
|
||||
//AlarmCfgWrapper* m_AlarmCfgWrapper;
|
||||
|
||||
ULONG m_WindowsVersion;
|
||||
bool m_UseSysApi;
|
||||
bool m_EnableProcessExtension;
|
||||
HMODULE m_HNtDll;
|
||||
PNTQUERYSYSTEMINFORMATION NtQuerySystemInformation = nullptr;
|
||||
pNtQueryInformationProcess NtQueryInformationProcess = nullptr;
|
||||
|
||||
Config* m_Config;
|
||||
};
|
||||
|
||||
131
utils/StringHelper.cpp
Normal file
131
utils/StringHelper.cpp
Normal file
@ -0,0 +1,131 @@
|
||||
#include "StringHelper.h"
|
||||
#include <vector>
|
||||
|
||||
|
||||
StringHelper::StringHelper()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
StringHelper::~StringHelper()
|
||||
{
|
||||
}
|
||||
|
||||
string StringHelper::AsciiToUtf8(const string& str)
|
||||
{
|
||||
int unicodeLen = MultiByteToWideChar(CP_ACP, 0, str.c_str(), -1, nullptr, 0);
|
||||
wchar_t *pUnicode = (wchar_t*)malloc(sizeof(wchar_t)*unicodeLen);
|
||||
MultiByteToWideChar(CP_ACP, 0, str.c_str(), -1, pUnicode, unicodeLen);
|
||||
int ansiiLen = WideCharToMultiByte(CP_UTF8, 0, pUnicode, -1, nullptr, 0, nullptr, nullptr);
|
||||
char *pAssii = (char*)malloc(sizeof(char)*ansiiLen);
|
||||
WideCharToMultiByte(CP_UTF8, 0, pUnicode, -1, pAssii, ansiiLen, nullptr, nullptr);
|
||||
string ret_str( pAssii);
|
||||
free(pUnicode);
|
||||
free(pAssii);
|
||||
return ret_str;
|
||||
}
|
||||
|
||||
string StringHelper::Utf8ToAscii(const string& str)
|
||||
{
|
||||
int unicodeLen = MultiByteToWideChar(CP_UTF8, 0, str.c_str(), -1, nullptr, 0);
|
||||
wchar_t* pUnicode = (wchar_t*)malloc(sizeof(wchar_t) * unicodeLen);
|
||||
MultiByteToWideChar(CP_UTF8, 0, str.c_str(), -1, pUnicode, unicodeLen);
|
||||
int ansiiLen = WideCharToMultiByte(CP_ACP, 0, pUnicode, -1, nullptr, 0, nullptr, nullptr);
|
||||
char* pAssii = (char*)malloc(sizeof(char) * ansiiLen);
|
||||
WideCharToMultiByte(CP_ACP, 0, pUnicode, -1, pAssii, ansiiLen, nullptr, nullptr);
|
||||
string ret_str(pAssii);
|
||||
free(pUnicode);
|
||||
free(pAssii);
|
||||
return ret_str;
|
||||
}
|
||||
|
||||
string StringHelper::GenerateUUID()
|
||||
{
|
||||
UUID uuid;
|
||||
::UuidCreate(&uuid);
|
||||
char buffer[50];
|
||||
sprintf_s(buffer, sizeof(buffer),
|
||||
"%08X%04X%04X%02X%02X%02X%02X%02X%02X%02X%02X",
|
||||
uuid.Data1, uuid.Data2, uuid.Data3,
|
||||
uuid.Data4[0], uuid.Data4[1], uuid.Data4[2],
|
||||
uuid.Data4[3], uuid.Data4[4], uuid.Data4[5],
|
||||
uuid.Data4[6], uuid.Data4[7]);
|
||||
return string(buffer);
|
||||
}
|
||||
|
||||
void StringHelper::Split(string str, char dim, vector<string>& rels)
|
||||
{
|
||||
char *strToken = NULL;
|
||||
char *next_token = NULL;
|
||||
strToken = strtok_s((char *)str.c_str(), &dim, &next_token);
|
||||
while (strToken != NULL) {
|
||||
rels.push_back(strToken);
|
||||
strToken = strtok_s(NULL, &dim, &next_token);
|
||||
}
|
||||
}
|
||||
|
||||
wstring StringHelper::Str2Wstr(string str)
|
||||
{
|
||||
wstring result;
|
||||
int len = MultiByteToWideChar(CP_ACP, 0, str.c_str(), str.size(), NULL, 0);
|
||||
wchar_t* buffer = new wchar_t[len + 1];
|
||||
MultiByteToWideChar(CP_ACP, 0, str.c_str(), str.size(), buffer, len);
|
||||
buffer[len] = '\0';
|
||||
result.append(buffer);
|
||||
delete[] buffer;
|
||||
return result;
|
||||
}
|
||||
|
||||
string StringHelper::Wstr2Str(wstring wstr)
|
||||
{
|
||||
if (wstr.empty())return "";
|
||||
int len = WideCharToMultiByte(CP_ACP, 0, wstr.c_str(), wstr.size(), NULL, 0, NULL, NULL);
|
||||
char* buffer = new char[len + 1];
|
||||
memset(buffer, '\0', len + 1);
|
||||
int nResult = WideCharToMultiByte(CP_ACP, 0, (LPCWSTR)wstr.c_str(), wstr.size(), buffer, len, NULL, NULL);
|
||||
if (nResult == 0)
|
||||
{
|
||||
return "";
|
||||
}
|
||||
string str(buffer);
|
||||
delete[]buffer;
|
||||
return str;
|
||||
}
|
||||
|
||||
string StringHelper::ReadString(ifstream* ifs)
|
||||
{
|
||||
char buffer[2048];
|
||||
memset(buffer, '\0', sizeof(buffer));
|
||||
int flag = 0;
|
||||
char temp;
|
||||
int pos = ifs->cur;
|
||||
while (!ifs->eof()) {
|
||||
ifs->get(temp);
|
||||
if (temp == '\0') {
|
||||
break;
|
||||
}
|
||||
else {
|
||||
buffer[flag] = temp;
|
||||
}
|
||||
flag++;
|
||||
if (flag >= sizeof(buffer)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
return string(buffer);
|
||||
}
|
||||
|
||||
string StringHelper::Double2String(double dvalue, string frt)
|
||||
{
|
||||
char buffer[123];
|
||||
sprintf_s(buffer, sizeof(buffer), frt.c_str(), dvalue);
|
||||
return string(buffer);
|
||||
}
|
||||
|
||||
|
||||
string StringHelper::GetAppPath() {
|
||||
char szFilePath[MAX_PATH + 1] = { 0 };
|
||||
GetModuleFileName(NULL, szFilePath, MAX_PATH);
|
||||
(strrchr(szFilePath, '\\'))[1] = 0;
|
||||
return string(szFilePath);
|
||||
}
|
||||
31
utils/StringHelper.h
Normal file
31
utils/StringHelper.h
Normal file
@ -0,0 +1,31 @@
|
||||
#pragma once
|
||||
#ifndef WIN32_LEAN_AND_MEAN
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#endif // !WIN32_LEAN_AND_MEAN
|
||||
|
||||
#include <windows.h>
|
||||
#include <tchar.h>
|
||||
#include <string>
|
||||
#include <atlbase.h>
|
||||
#include <vector>
|
||||
#include <fstream>
|
||||
using namespace std;
|
||||
|
||||
class StringHelper
|
||||
{
|
||||
public:
|
||||
StringHelper();
|
||||
~StringHelper();
|
||||
|
||||
static string AsciiToUtf8(const string& str);
|
||||
static string Utf8ToAscii(const string& str);
|
||||
static string GenerateUUID();
|
||||
static void Split(string str, char dim, vector<string>& rels);
|
||||
static wstring Str2Wstr(string str);
|
||||
static string Wstr2Str(wstring str);
|
||||
static string ReadString(ifstream* ifs);
|
||||
static string Double2String(double dvalue, string frt = "%.12f");
|
||||
|
||||
static string GetAppPath();
|
||||
};
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user