Skip to content

Commit

Permalink
Adds "devcon install" compatible command and major refactor (#16)
Browse files Browse the repository at this point in the history
* Reworked error propagation

* Update Devcon.cpp

* Added API doc

* Added MultiStringArray

Code clean-up

* Added missing namespace

* Update Devcon.cpp

* Simplifications

* Update Devcon.cpp

* More conversions

* Update Devcon.cpp

* Added devcon::update

* Enabled C++23

* Used that modern magic

* Improving error propagation

* Update vcpkg.json

* More fancy stuff

* Reworked devcon::create

* Update Devcon.cpp

* Code clean-up

Refined API docs

* Reworked more functions

* Improved utility class

* Improved utility class

* Update Devcon.cpp

* Added GetDeviceRegistryProperty

* Reworked devcon::restart_bth_usb_device

* Update Devcon.cpp

* Reworked devcon::enable_disable_bth_usb_device

* Update Devcon.cpp

* Reworked uninstall_device_and_driver

* Update Devcon.cpp

* Reworked devcon::uninstall_device_and_driver

* More memory voodoo

* Update Devcon.cpp

* Update Devcon.cpp

* Formatting

* Hardened INF path processing

* Reworked devcon::inf_default_install

* Update Devcon.cpp

* Reworked devcon::inf_default_uninstall

* Update Devcon.cpp

* Update Devcon.cpp

* Added INFHandleGuard

* Added HDEVINFOHandleGuard

* More scope fun

* Reworked find_by_hwid

* Reworked devcon::find_by_hwid

Bugfixes in property reading

* Update Devcon.cpp

* Improved abstractions

* Update NefConUtil.cpp

* Update README.md

* Update README.md

* Update README.md

* Update NefConUtil.cpp

* Converted filter functions

* More modernization

* Update Devcon.cpp

* Updated docs

* Update README.md

* Update Devcon.h

* Update Devcon.h

* Update Devcon.cpp

* Update NefConUtil.cpp

* Reworking colors in console logger

* Color logging overhaul

* Removed unused code

* Update ColorLogging.hpp

* Update ColorLogging.hpp

* Update NefConUtil.cpp

* Removed duplicate logging to stdout

* Started moving shared code to https://github.com/nefarius/neflib

* Migrated stuff to neflib

* Another migration

* Migrated more functions

* Migrated more chunks to neflib

* Reworked API breaking change

* Update vcpkg-configuration.json

* Update vcpkg-configuration.json

* Update vcpkg-configuration.json

* Removed migrated types

* Update NefConUtil.cpp

* Migrated more functions

* Update vcpkg-configuration.json

* Update README.md

* Update vcpkg-configuration.json

* Fixed build issue

* Update msbuild.yml

* Ported CLI args helper

* Updated neflib

* Update vcpkg-configuration.json

* neflib updates

* Update vcpkg-configuration.json

* Update vcpkg-configuration.json

* Update vcpkg-configuration.json

* Update vcpkg-configuration.json

* Updated neflib

* Update NefConUtil.cpp

* Update vcpkg-configuration.json

* Update vcpkg-configuration.json

* Removed and replaced deprecated code

* Updated neflib

* Update NefConUtil.cpp

* CA fixes

* Implemented install command

* Update NefConUtil.cpp

* Exit code and logging fix

* Update README.md

* Update README.md

* Update vcpkg-configuration.json

* Update vcpkg-configuration.json

* Update NefConUtil.sln.DotSettings

* Update NefConUtil.cpp
  • Loading branch information
nefarius authored Aug 26, 2024
1 parent 030a020 commit 5deadb7
Show file tree
Hide file tree
Showing 19 changed files with 429 additions and 2,225 deletions.
11 changes: 8 additions & 3 deletions .github/workflows/msbuild.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@ env:
# Configuration type to build.
# You can convert this to a build matrix if you need coverage of multiple configuration types.
# https://docs.github.com/actions/learn-github-actions/managing-complex-workflows#using-a-build-matrix
BUILD_CONFIGURATION: Release (Console)
BUILD_PLATFORM: x64

permissions:
Expand All @@ -38,8 +37,14 @@ jobs:
working-directory: ${{env.GITHUB_WORKSPACE}}
run: vcpkg integrate install

- name: Build
- name: Build Console Edition
working-directory: ${{env.GITHUB_WORKSPACE}}
# Add additional options to the MSBuild command line here (like platform or verbosity level).
# See https://docs.microsoft.com/visualstudio/msbuild/msbuild-command-line-reference
run: msbuild /m /p:Configuration="${{env.BUILD_CONFIGURATION}}" /p:Platform=${{env.BUILD_PLATFORM}} ${{env.SOLUTION_FILE_PATH}}
run: msbuild /m /p:Configuration="Release (Console)" /p:Platform=${{env.BUILD_PLATFORM}} ${{env.SOLUTION_FILE_PATH}}

- name: Build WinMain Edition
working-directory: ${{env.GITHUB_WORKSPACE}}
# Add additional options to the MSBuild command line here (like platform or verbosity level).
# See https://docs.microsoft.com/visualstudio/msbuild/msbuild-command-line-reference
run: msbuild /m /p:Configuration="Release (WinMain)" /p:Platform=${{env.BUILD_PLATFORM}} ${{env.SOLUTION_FILE_PATH}}
11 changes: 11 additions & 0 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
{
"cSpell.words": [
"devcon",
"nefcon",
"nefconc",
"nefconw",
"pkgs",
"pnputil",
"winget"
]
}
15 changes: 14 additions & 1 deletion NefConUtil.sln.DotSettings
Original file line number Diff line number Diff line change
@@ -1,18 +1,31 @@
<wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:ss="urn:shemas-jetbrains-com:settings-storage-xaml" xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
<s:Boolean x:Key="/Default/UserDictionary/Words/=attribs/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=Bugprone/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=cmdl/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=cppcoreguidelines/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=DEVICEDESC/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=efcon/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=efconc/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=efconw/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=ELPP/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=HDEVINFO/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=Hicpp/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=Hinf/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=HKEY/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=Hoeglinger/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=hwid/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=luid/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=matchstring/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=nefarius/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=nefcon/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=nefconc/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=neflib/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=Newdev/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=Printf/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=SPDRP/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=Stelzer/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=winapi/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=wstring/@EntryIndexedValue">True</s:Boolean></wpf:ResourceDictionary>
<s:Boolean x:Key="/Default/UserDictionary/Words/=wstring/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=xxxx/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=xxxxxxxx/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=xxxxxxxxxxxx/@EntryIndexedValue">True</s:Boolean></wpf:ResourceDictionary>
32 changes: 14 additions & 18 deletions NefConUtil.vcxproj
Original file line number Diff line number Diff line change
Expand Up @@ -295,7 +295,7 @@
<PreprocessorDefinitions>_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
<LanguageStandard>stdcpp17</LanguageStandard>
<LanguageStandard>stdcpplatest</LanguageStandard>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
Expand All @@ -313,7 +313,7 @@
<PreprocessorDefinitions>_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
<LanguageStandard>stdcpp17</LanguageStandard>
<LanguageStandard>stdcpplatest</LanguageStandard>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
Expand All @@ -331,7 +331,7 @@
<PreprocessorDefinitions>NEFCON_WINMAIN;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
<LanguageStandard>stdcpp17</LanguageStandard>
<LanguageStandard>stdcpplatest</LanguageStandard>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
Expand All @@ -349,7 +349,7 @@
<PreprocessorDefinitions>NEFCON_WINMAIN;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
<LanguageStandard>stdcpp17</LanguageStandard>
<LanguageStandard>stdcpplatest</LanguageStandard>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
Expand All @@ -367,7 +367,7 @@
<PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
<LanguageStandard>stdcpp17</LanguageStandard>
<LanguageStandard>stdcpplatest</LanguageStandard>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
Expand All @@ -385,7 +385,7 @@
<PreprocessorDefinitions>NEFCON_WINMAIN;WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
<LanguageStandard>stdcpp17</LanguageStandard>
<LanguageStandard>stdcpplatest</LanguageStandard>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
Expand All @@ -406,7 +406,7 @@
<ConformanceMode>true</ConformanceMode>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
<DebugInformationFormat>None</DebugInformationFormat>
<LanguageStandard>stdcpp17</LanguageStandard>
<LanguageStandard>stdcpplatest</LanguageStandard>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
Expand All @@ -429,7 +429,7 @@
<ConformanceMode>true</ConformanceMode>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
<DebugInformationFormat>None</DebugInformationFormat>
<LanguageStandard>stdcpp17</LanguageStandard>
<LanguageStandard>stdcpplatest</LanguageStandard>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
Expand All @@ -452,7 +452,7 @@
<ConformanceMode>true</ConformanceMode>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
<DebugInformationFormat>None</DebugInformationFormat>
<LanguageStandard>stdcpp17</LanguageStandard>
<LanguageStandard>stdcpplatest</LanguageStandard>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
Expand All @@ -475,7 +475,7 @@
<ConformanceMode>true</ConformanceMode>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
<DebugInformationFormat>None</DebugInformationFormat>
<LanguageStandard>stdcpp17</LanguageStandard>
<LanguageStandard>stdcpplatest</LanguageStandard>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
Expand All @@ -498,7 +498,7 @@
<ConformanceMode>true</ConformanceMode>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
<DebugInformationFormat>None</DebugInformationFormat>
<LanguageStandard>stdcpp17</LanguageStandard>
<LanguageStandard>stdcpplatest</LanguageStandard>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
Expand All @@ -521,7 +521,7 @@
<ConformanceMode>true</ConformanceMode>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
<DebugInformationFormat>None</DebugInformationFormat>
<LanguageStandard>stdcpp17</LanguageStandard>
<LanguageStandard>stdcpplatest</LanguageStandard>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
Expand All @@ -532,24 +532,20 @@
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include=".\src\Devcon.cpp" />
<ClCompile Include=".\src\NefConSetup.cpp" />
<ClCompile Include=".\src\NefConUtil.cpp" />
</ItemGroup>
<ItemGroup>
<ClInclude Include=".\src\Devcon.h" />
<ClInclude Include=".\src\framework.h" />
<ClInclude Include=".\src\LibraryHelper.hpp" />
<ClInclude Include=".\src\NefConSetup.h" />
<ClInclude Include=".\src\NefConUtil.h" />
<ClInclude Include=".\src\colorwin.hpp" />
<ClInclude Include=".\src\resource.h" />
<ClInclude Include=".\src\UniUtil.h" />
<ClInclude Include="src\ColorLogging.hpp" />
</ItemGroup>
<ItemGroup>
<ResourceCompile Include=".\src\NefConUtil.rc" />
</ItemGroup>
<ItemGroup>
<None Include="vcpkg-configuration.json" />
<None Include="vcpkg.json" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
Expand Down
18 changes: 2 additions & 16 deletions NefConUtil.vcxproj.filters
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,6 @@
<ClCompile Include=".\src\NefConUtil.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include=".\src\Devcon.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include=".\src\NefConSetup.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include=".\src\resource.h">
Expand All @@ -35,19 +29,10 @@
<ClInclude Include=".\src\NefConUtil.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include=".\src\Devcon.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include=".\src\framework.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include=".\src\LibraryHelper.hpp">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include=".\src\NefConSetup.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include=".\src\UniUtil.h">
<ClInclude Include="src\ColorLogging.hpp">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
Expand All @@ -58,5 +43,6 @@
</ItemGroup>
<ItemGroup>
<None Include="vcpkg.json" />
<None Include="vcpkg-configuration.json" />
</ItemGroup>
</Project>
27 changes: 26 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,26 +1,45 @@
# <img src="assets/NSS-128x128.png" align="left" />nefcon

[![MSBuild](https://github.com/nefarius/nefcon/actions/workflows/msbuild.yml/badge.svg)](https://github.com/nefarius/nefcon/actions/workflows/msbuild.yml) [![GitHub All Releases](https://img.shields.io/github/downloads/nefarius/nefcon/total)](https://somsubhra.github.io/github-release-stats/?username=nefarius&repository=nefcon)
[![MSBuild](https://github.com/nefarius/nefcon/actions/workflows/msbuild.yml/badge.svg)](https://github.com/nefarius/nefcon/actions/workflows/msbuild.yml)
[![GitHub All Releases](https://img.shields.io/github/downloads/nefarius/nefcon/total)](https://somsubhra.github.io/github-release-stats/?username=nefarius&repository=nefcon)
[![Discord](https://img.shields.io/discord/346756263763378176.svg)](https://discord.nefarius.at)
[![GitHub followers](https://img.shields.io/github/followers/nefarius.svg?style=social&label=Follow)](https://github.com/nefarius)
[![Mastodon Follow](https://img.shields.io/mastodon/follow/109321120351128938?domain=https%3A%2F%2Ffosstodon.org%2F&style=social)](https://fosstodon.org/@Nefarius)

Windows device driver installation and management tool.

## About

This little self-contained, no-dependency tool can be built either as a console application or a Windows application which has no visible window (ideal to use in combination with setup makers). It offers a command-line-based driver (un-)installer and allows for simple manipulation of class filter entries. Run `nefconc.exe --help` to see all the options offered.

## Motivation

Windows Device Driver management is and always has been hard. The APIs involved are old, moody and come with pitfalls. Historically the [`devcon`](https://github.com/microsoft/Windows-driver-samples/tree/b3af8c8f9bd508f54075da2f2516b31d05cd52c8/setup/devcon) tool or nowadays `pnputil` have been used to offload these tedious tasks, but unintuitive and sparsely documented command line arguments and error propagation make them poor candidates for automation in e.g. setup engines. Grown tired of these limitations I made this "devcon clone" available under a permissive license which offers the following highlighted features and more:

- Allows for true window-less execution
- Actively suppresses and works around user interaction inconsistencies ("reboot required" dialogs and OS-included bugs)
- Offers optional logging to `stdout` or file
- *Sane* command line arguments 😁
- [Class filter](https://learn.microsoft.com/en-us/windows-hardware/drivers/kernel/filter-drivers) values manipulation
- Supports installation of [primitive drivers](https://learn.microsoft.com/en-us/windows-hardware/drivers/develop/creating-a-primitive-driver)

## Installation

Binaries are available to download in the [releases](https://github.com/nefarius/nefcon/releases/latest) page, just download and extract. However, if you are using a package manager, you can use one of the following options:

### Scoop

[`nefcon`](https://scoop.sh/#/apps?q=nefcon&s=0&d=1&o=true) is available in the [Extras](https://github.com/ScoopInstaller/Extras) bucket:

```text
scoop bucket add extras
scoop install nefcon
```

### Winget

[`nefcon`](https://github.com/microsoft/winget-pkgs/tree/master/manifests/n/Nefarius/nefcon) is available in the [winget-pkgs](https://github.com/microsoft/winget-pkgs) repository:

```text
winget install nefcon
```
Expand Down Expand Up @@ -74,3 +93,9 @@ This project uses the following 3rd party resources:
- [Convenient high-level C++ wrappers around Windows Registry Win32 APIs](https://github.com/GiovanniDicanio/WinReg)
- [Single header C++ logging library](https://github.com/amrayn/easyloggingpp)
- [Microsoft Detours](https://github.com/microsoft/Detours)
- [A modern C++ scope guard that is easy to use but hard to misuse](https://github.com/ricab/scope_guard)
- [Windows Implementation Libraries (WIL)](https://github.com/microsoft/wil)
- [My opinionated collection of C++ utilities](https://github.com/nefarius/neflib)
- [Replacing Device Console (DevCon.exe)](https://learn.microsoft.com/en-us/windows-hardware/drivers/devtest/devcon-migration)
- [PnPUtil](https://learn.microsoft.com/en-us/windows-hardware/drivers/devtest/pnputil)
- [DevCon Install](https://learn.microsoft.com/en-us/windows-hardware/drivers/devtest/devcon-install)
51 changes: 51 additions & 0 deletions src/ColorLogging.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
#pragma once

#include <chrono>
#include <map>
#include "colorwin.hpp"
#include <easylogging++.h>

/**
* Custom log dispatcher printing on the console (terminal) with color support.
*
* @author Benjamin "Nefarius" Hoeglinger-Stelzer
* @date 08.08.2024
*/
class ConsoleColorLogDispatchCallback : public el::LogDispatchCallback
{
std::unordered_map<el::Level, colorwin::CW_COLORS> logLevelToColor = {
{el::Level::Debug, colorwin::white},
{el::Level::Info, colorwin::green},
{el::Level::Warning, colorwin::yellow},
{el::Level::Error, colorwin::red},
{el::Level::Fatal, colorwin::magenta},
{el::Level::Verbose, colorwin::white}
};

protected:
void handle(const el::LogDispatchData* data) noexcept override
{
// Extract log message details
const el::LogMessage* logMessage = data->logMessage();
const auto now = std::chrono::system_clock::now();
std::string timestamp = std::format("{:%FT%TZ}", std::chrono::time_point_cast<std::chrono::seconds>(now));
std::string level = logMessage->level() == el::Level::Debug
? "DEBUG"
: logMessage->level() == el::Level::Info
? "INFO"
: logMessage->level() == el::Level::Warning
? "WARNING"
: logMessage->level() == el::Level::Error
? "ERROR"
: logMessage->level() == el::Level::Fatal
? "FATAL"
: "VERBOSE";
std::string message = logMessage->message();

// scoped color
{
std::cout << timestamp << " " << colorwin::color(logLevelToColor[logMessage->level()]) << level;
}
std::cout << " " << message << '\n';
}
};
Loading

0 comments on commit 5deadb7

Please sign in to comment.