上传文件

This commit is contained in:
wangxx1809 2025-08-20 11:22:14 +08:00
commit b0065a876c
26 changed files with 10830 additions and 0 deletions

10
.gitignore vendored Normal file
View File

@ -0,0 +1,10 @@
################################################################################
# 此 .gitignore 文件已由 Microsoft(R) Visual Studio 自动创建。
################################################################################
/.vs
/*.user
/*.filters
/x64/*
/*.log
/*.zip

31
MemoryCheck.sln Normal file
View 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
View 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>

0
README.md Normal file
View File

171
include/INIH/INIReader.cpp Normal file
View 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
View 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
View 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
View File

@ -0,0 +1,175 @@
# inih (INI Not Invented Here)
[![Tests](https://github.com/benhoyt/inih/actions/workflows/tests.yml/badge.svg)](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
View 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
View 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
View 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.

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

280
main.cpp Normal file
View 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
View 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
View File

@ -0,0 +1,8 @@
cd /d "%~dp0"
echo Current directory: %CD%
MemoryCheck.exe /install
pause

18
resource/log.conf Normal file
View 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

Binary file not shown.

BIN
resource/pslist.exe Normal file

Binary file not shown.

9
resource/uninstall.bat Normal file
View File

@ -0,0 +1,9 @@
cd /d "%~dp0"
echo Current directory: %CD%
MemoryCheck.exe /uninstall
pause

53
src/Config.h Normal file
View 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
View 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
View 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
View 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
View 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
View 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();
};