From 30826b3bdca341e9f875b613eb2d7cffa67251f6 Mon Sep 17 00:00:00 2001 From: fabienfl Date: Thu, 29 Feb 2024 14:02:31 +0100 Subject: [PATCH 01/60] OrcLib: Utils: add MapFile --- src/OrcLib/CMakeLists.txt | 2 + src/OrcLib/Utils/MapFile.cpp | 86 ++++++++++++++++++++++++++++++++++++ src/OrcLib/Utils/MapFile.h | 20 +++++++++ 3 files changed, 108 insertions(+) create mode 100644 src/OrcLib/Utils/MapFile.cpp create mode 100644 src/OrcLib/Utils/MapFile.h diff --git a/src/OrcLib/CMakeLists.txt b/src/OrcLib/CMakeLists.txt index b63178a2..141e0676 100644 --- a/src/OrcLib/CMakeLists.txt +++ b/src/OrcLib/CMakeLists.txt @@ -831,6 +831,8 @@ set(SRC_UTILITIES "Utils/Guard/Winsock.cpp" "Utils/Locker.h" "Utils/MakeArray.h" + "Utils/MapFile.h" + "Utils/MapFile.cpp" "Utils/MetaPtr.h" "Utils/Result.h" "Utils/Round.h" diff --git a/src/OrcLib/Utils/MapFile.cpp b/src/OrcLib/Utils/MapFile.cpp new file mode 100644 index 00000000..5c5cd06e --- /dev/null +++ b/src/OrcLib/Utils/MapFile.cpp @@ -0,0 +1,86 @@ +// +// SPDX-License-Identifier: LGPL-2.1-or-later +// +// Copyright © 2024 ANSSI. All Rights Reserved. +// +// Author(s): fabienfl (ANSSI) +// + +#include "Utils/MapFile.h" + +#include "Utils/Result.h" +#include "Utils/Guard.h" + +using namespace Orc; + +namespace { + +Result GetFileSize(HANDLE hFile) +{ + LARGE_INTEGER fileSize; + if (!GetFileSizeEx(hFile, &fileSize)) + { + return LastWin32Error(); + } + + return fileSize.QuadPart; +} + +} // namespace + +namespace Orc { + +Result> MapFile(const std::filesystem::path& path) +{ + Guard::FileHandle file = CreateFileW( + path.c_str(), + GENERIC_READ, + FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, + NULL, + OPEN_EXISTING, + FILE_ATTRIBUTE_NORMAL, + NULL); + if (!file.IsValid()) + { + auto ec = LastWin32Error(); + Log::Debug("Failed CreateFile [{}]", ec); + return ec; + } + + auto bytesToRead = GetFileSize(file.value()); + if (bytesToRead.has_error()) + { + Log::Debug("Failed GetFileSizeEx [{}]", bytesToRead.error()); + return bytesToRead.error(); + } + + if (*bytesToRead > UINT32_MAX) + { + Log::Debug("File is too big"); + return std::make_error_code(std::errc::no_buffer_space); + } + + std::vector buffer; + + try + { + buffer.resize(*bytesToRead); + } + catch (const std::exception& e) + { + Log::Debug("Failed to resize buffer [{}]", e.what()); + return std::make_error_code(std::errc::no_buffer_space); + } + + DWORD bytesRead = 0; + if (!ReadFile(file.value(), buffer.data(), static_cast(buffer.size()), &bytesRead, NULL)) + { + auto ec = LastWin32Error(); + Log::Debug("Failed ReadFile [{}]", ec); + return ec; + } + + return buffer; +} + +} // namespace Orc diff --git a/src/OrcLib/Utils/MapFile.h b/src/OrcLib/Utils/MapFile.h new file mode 100644 index 00000000..45ecdfe9 --- /dev/null +++ b/src/OrcLib/Utils/MapFile.h @@ -0,0 +1,20 @@ +// +// SPDX-License-Identifier: LGPL-2.1-or-later +// +// Copyright © 2024 ANSSI. All Rights Reserved. +// +// Author(s): fabienfl (ANSSI) +// + +#pragma once + +#include +#include + +#include "Utils/Result.h" + +namespace Orc { + +Result> MapFile(const std::filesystem::path& path); + +} // namespace Orc From 958dd6891cd8ee34f19d85a8b69c95818ba41ef1 Mon Sep 17 00:00:00 2001 From: fabienfl Date: Tue, 13 Feb 2024 20:35:34 +0100 Subject: [PATCH 02/60] OrcLib: Utils: add StackStash --- src/OrcLib/CMakeLists.txt | 1 + src/OrcLib/Utils/StackStash.h | 30 ++++++++++++++++++++++++++++++ 2 files changed, 31 insertions(+) create mode 100644 src/OrcLib/Utils/StackStash.h diff --git a/src/OrcLib/CMakeLists.txt b/src/OrcLib/CMakeLists.txt index 141e0676..c8c321ff 100644 --- a/src/OrcLib/CMakeLists.txt +++ b/src/OrcLib/CMakeLists.txt @@ -836,6 +836,7 @@ set(SRC_UTILITIES "Utils/MetaPtr.h" "Utils/Result.h" "Utils/Round.h" + "Utils/StackStash.h" "Utils/String.cpp" "Utils/String.h" "Utils/Time.cpp" diff --git a/src/OrcLib/Utils/StackStash.h b/src/OrcLib/Utils/StackStash.h new file mode 100644 index 00000000..2615898a --- /dev/null +++ b/src/OrcLib/Utils/StackStash.h @@ -0,0 +1,30 @@ +// +// SPDX-License-Identifier: LGPL-2.1-or-later +// +// Copyright © 2024 ANSSI. All Rights Reserved. +// +// Author(s): fabienfl (ANSSI) +// +#pragma once + +#include +#include + +namespace Orc { + +template +class StackStash final : public std::pmr::polymorphic_allocator +{ +public: + StackStash() + : std::pmr::polymorphic_allocator(&m_resource) + , m_resource(m_stack.data(), Elements * sizeof(T)) + { + } + +private: + std::array m_stack; + std::pmr::monotonic_buffer_resource m_resource; +}; + +} // namespace Orc From ff69f826c19bcb330ec27096c46891a33578e7c5 Mon Sep 17 00:00:00 2001 From: fabienfl Date: Wed, 28 Feb 2024 14:58:31 +0100 Subject: [PATCH 03/60] OrcLib: Utils: Dump: replace fstream with win32 api --- src/OrcLib/Utils/Dump.h | 41 +++++++++++++++++++++++++++++++++++++---- 1 file changed, 37 insertions(+), 4 deletions(-) diff --git a/src/OrcLib/Utils/Dump.h b/src/OrcLib/Utils/Dump.h index 7a36b653..0d0b3a5c 100644 --- a/src/OrcLib/Utils/Dump.h +++ b/src/OrcLib/Utils/Dump.h @@ -8,16 +8,49 @@ #pragma once -#include #include +#include "Utils/Result.h" +#include "Utils/Guard.h" + namespace Orc { template -void Dump(const T& container, const std::filesystem::path& output) +Result Dump(const T& container, const std::filesystem::path& output) { - std::ofstream ofs(output, std::ios_base::binary); - std::copy(std::cbegin(container), std::cend(container), std::ostreambuf_iterator(ofs)); + using value_type = T::value_type; + std::string_view buffer(reinterpret_cast(container.data()), container.size() * sizeof(T::value_type)); + + Guard::FileHandle file = CreateFileW( + output.c_str(), + GENERIC_WRITE, + FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, + NULL, + CREATE_NEW, + FILE_ATTRIBUTE_NORMAL, + NULL); + if (!file.IsValid()) + { + auto ec = LastWin32Error(); + Log::Debug("Failed CreateFile [{}]", ec); + return ec; + } + + DWORD written = 0; + if (!WriteFile(file.value(), buffer.data(), static_cast(buffer.size()), &written, NULL)) + { + auto ec = LastWin32Error(); + Log::Debug("Failed WriteFile [{}]", ec); + return ec; + } + + if (written != buffer.size()) + { + Log::Debug("Partial write (expected: {}, done: {})", buffer.size(), written); + return std::make_error_code(std::errc::message_size); + } + + return Orc::Success<>(); } } // namespace Orc From 61c3cb4a0a720fc34a39ed580881f8705997fbe3 Mon Sep 17 00:00:00 2001 From: fabienfl Date: Thu, 7 Mar 2024 17:13:04 +0100 Subject: [PATCH 04/60] OrcLib: Utils: Result: ToHRESULT: handle other category than 'system' --- src/OrcLib/Utils/Result.h | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/OrcLib/Utils/Result.h b/src/OrcLib/Utils/Result.h index 3963ae4c..d7ed2012 100644 --- a/src/OrcLib/Utils/Result.h +++ b/src/OrcLib/Utils/Result.h @@ -146,7 +146,11 @@ inline std::error_code LastWin32Error() inline HRESULT ToHRESULT(const std::error_code& ec) { - assert(ec.category() == std::system_category()); + if (ec.category() != std::system_category()) + { + return ec ? E_FAIL : S_OK; + } + auto hr = ec.value(); if ((hr & 0xF0000000) == 0x80000000) { From 5ad9885c7eec05d47f1ebccf1b2ed274790bdd06 Mon Sep 17 00:00:00 2001 From: fabienfl Date: Tue, 8 Aug 2023 17:26:45 +0200 Subject: [PATCH 05/60] OrcLib: Utils: MetaPtr: fix missing operator() --- src/OrcLib/Utils/MetaPtr.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/OrcLib/Utils/MetaPtr.h b/src/OrcLib/Utils/MetaPtr.h index 9d89d478..70fc171d 100644 --- a/src/OrcLib/Utils/MetaPtr.h +++ b/src/OrcLib/Utils/MetaPtr.h @@ -95,7 +95,7 @@ class Stack } constexpr T* operator->() { return &value; } - constexpr T* operator->() const { return &value; } + constexpr const T* operator->() const { return &value; } constexpr T& operator*() { return value; } constexpr const T& operator*() const { return value; } From db77e5d79419e65afa999b2620cd5eeee7bcb704 Mon Sep 17 00:00:00 2001 From: fabienfl Date: Tue, 8 Aug 2023 17:27:24 +0200 Subject: [PATCH 06/60] OrcLib: Utils: MetaPtr: add element_type --- src/OrcLib/Utils/MetaPtr.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/OrcLib/Utils/MetaPtr.h b/src/OrcLib/Utils/MetaPtr.h index 70fc171d..02703417 100644 --- a/src/OrcLib/Utils/MetaPtr.h +++ b/src/OrcLib/Utils/MetaPtr.h @@ -88,6 +88,8 @@ class Stack class PtrAdapter final { public: + using element_type = T; + template PtrAdapter(Args&&... args) : value(std::forward(args)...) @@ -118,6 +120,8 @@ class Reference class PtrAdapter final { public: + using element_type = T; + PtrAdapter(T& ref) : value(ref) { From 667deac895470ff1153a77e331099c76920d1166 Mon Sep 17 00:00:00 2001 From: fabienfl Date: Tue, 8 Aug 2023 17:28:14 +0200 Subject: [PATCH 07/60] OrcLib: Utils: MetaPtr: add method get --- src/OrcLib/Utils/MetaPtr.h | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/OrcLib/Utils/MetaPtr.h b/src/OrcLib/Utils/MetaPtr.h index 02703417..5bed7301 100644 --- a/src/OrcLib/Utils/MetaPtr.h +++ b/src/OrcLib/Utils/MetaPtr.h @@ -102,6 +102,9 @@ class Stack constexpr T& operator*() { return value; } constexpr const T& operator*() const { return value; } + constexpr T* get() { return &value; } + constexpr const T* get() const { return &value; } + private: T value; }; @@ -133,6 +136,9 @@ class Reference constexpr T& operator*() { return value; } constexpr const T& operator*() const { return value; } + constexpr T* get() { return &value; } + constexpr const T* get() const { return &value; } + private: T& value; }; From d7b534997ce58a6812ce205e8781efb52985aee1 Mon Sep 17 00:00:00 2001 From: fabienfl Date: Fri, 8 Mar 2024 16:08:11 +0100 Subject: [PATCH 08/60] OrcLib: CacheStream: use reference for underlying stream --- src/OrcLib/Authenticode.cpp | 3 ++- src/OrcLib/CacheStream.cpp | 16 ++++++++-------- src/OrcLib/CacheStream.h | 15 ++++++++------- src/OrcLib/FileFormat/PeParser.cpp | 18 +++++++++--------- src/OrcLib/FileFormat/PeParser.h | 4 ++-- src/OrcLib/PEInfo.cpp | 7 ++++--- 6 files changed, 33 insertions(+), 30 deletions(-) diff --git a/src/OrcLib/Authenticode.cpp b/src/OrcLib/Authenticode.cpp index 86aa03ff..d18ca405 100644 --- a/src/OrcLib/Authenticode.cpp +++ b/src/OrcLib/Authenticode.cpp @@ -665,7 +665,8 @@ HRESULT Authenticode::Verify(LPCWSTR szFileName, const std::shared_ptr(pStream), ec); + CacheStream cache(*pStream, 1048576); + PeParser pe(cache, ec); if (ec) { Log::Debug(L"Failed to parse pe file (filename: {}) [{}]", szFileName, ec); diff --git a/src/OrcLib/CacheStream.cpp b/src/OrcLib/CacheStream.cpp index f8a5f6c7..9f1c422f 100644 --- a/src/OrcLib/CacheStream.cpp +++ b/src/OrcLib/CacheStream.cpp @@ -14,9 +14,9 @@ using namespace std::string_view_literals; namespace Orc { -CacheStream::CacheStream(std::shared_ptr stream, size_t cacheSize) +CacheStream::CacheStream(ByteStream& stream, size_t cacheSize) : ByteStream() - , m_stream(std::move(stream)) + , m_stream(stream) , m_streamOffset(0) , m_offset(0) , m_cache() @@ -27,14 +27,14 @@ CacheStream::CacheStream(std::shared_ptr stream, size_t cacheSize) m_cache.resize(cacheSize); } -STDMETHODIMP Orc::CacheStream::Clone(std::shared_ptr& clone) +STDMETHODIMP Orc::CacheStream::Clone(ByteStream& clone) { return E_NOTIMPL; } HRESULT CacheStream::Close() { - HRESULT hr = m_stream->Close(); + HRESULT hr = m_stream.Close(); if (FAILED(hr)) { Log::Debug("Failed to close underlying cached stream [{}]", SystemError(hr)); @@ -59,7 +59,7 @@ HRESULT CacheStream::Duplicate(const CacheStream& other) HRESULT CacheStream::Open() { - HRESULT hr = m_stream->IsOpen(); + HRESULT hr = m_stream.IsOpen(); if (hr != S_OK) { Log::Debug("Failed to open CacheStream: underlying stream is closed [{}]", SystemError(hr)); @@ -107,7 +107,7 @@ HRESULT CacheStream::Read_( else { ULONGLONG streamRead = 0; - hr = m_stream->Read(m_cache.data(), m_cache.size(), &streamRead); + hr = m_stream.Read(m_cache.data(), m_cache.size(), &streamRead); if (FAILED(hr)) { return hr; @@ -149,7 +149,7 @@ CacheStream::SetFilePointer(__in LONGLONG DistanceToMove, __in DWORD dwMoveMetho pCurrPointer = &newOffset; } - HRESULT hr = m_stream->SetFilePointer(DistanceToMove, dwMoveMethod, pCurrPointer); + HRESULT hr = m_stream.SetFilePointer(DistanceToMove, dwMoveMethod, pCurrPointer); if (FAILED(hr)) { return hr; @@ -162,7 +162,7 @@ CacheStream::SetFilePointer(__in LONGLONG DistanceToMove, __in DWORD dwMoveMetho ULONG64 CacheStream::GetSize() { - return m_stream->GetSize(); + return m_stream.GetSize(); } HRESULT CacheStream::SetSize(ULONG64 ullNewSize) diff --git a/src/OrcLib/CacheStream.h b/src/OrcLib/CacheStream.h index b1918351..3f2b8d10 100644 --- a/src/OrcLib/CacheStream.h +++ b/src/OrcLib/CacheStream.h @@ -10,7 +10,8 @@ #include "OrcLib.h" -#include "MemoryStream.h" +#include "ByteStream.h" +#include "Utils/MetaPtr.h" #pragma managed(push, off) @@ -21,17 +22,17 @@ class CBinaryBuffer; class CacheStream : public ByteStream { public: - CacheStream(std::shared_ptr stream, size_t cacheSize = 1048576); + CacheStream(ByteStream& stream, size_t cacheSize); ~CacheStream(); HRESULT Open(); void Accept(ByteStreamVisitor& visitor) override { return visitor.Visit(*this); }; - STDMETHOD(IsOpen)() { return m_stream->IsOpen(); }; + STDMETHOD(IsOpen)() { return m_stream.IsOpen(); }; - STDMETHOD(CanRead)() { return m_stream->CanRead(); }; + STDMETHOD(CanRead)() { return m_stream.CanRead(); }; STDMETHOD(CanWrite)() { return S_FALSE; }; - STDMETHOD(CanSeek)() { return m_stream->CanSeek(); }; + STDMETHOD(CanSeek)() { return m_stream.CanSeek(); }; // // CByteStream implementation @@ -52,13 +53,13 @@ class CacheStream : public ByteStream STDMETHOD_(ULONG64, GetSize)(); STDMETHOD(SetSize)(ULONG64 ullSize); - STDMETHOD(Clone)(std::shared_ptr& clone); + STDMETHOD(Clone)(ByteStream& clone); STDMETHOD(Close)(); HRESULT Duplicate(const CacheStream& other); private: - std::shared_ptr m_stream; + ByteStream& m_stream; uint64_t m_streamOffset; uint64_t m_offset; std::vector m_cache; diff --git a/src/OrcLib/FileFormat/PeParser.cpp b/src/OrcLib/FileFormat/PeParser.cpp index 4ade15fa..8fbede79 100644 --- a/src/OrcLib/FileFormat/PeParser.cpp +++ b/src/OrcLib/FileFormat/PeParser.cpp @@ -193,23 +193,23 @@ void ParseImageSections( namespace Orc { -PeParser::PeParser(std::shared_ptr stream, std::error_code& ec) - : m_stream(std::move(stream)) +PeParser::PeParser(ByteStream& stream, std::error_code& ec) + : m_stream(stream) { - ::ParseImageDosHeader(*m_stream, m_imageDosHeader, ec); + ::ParseImageDosHeader(m_stream, m_imageDosHeader, ec); if (ec) { return; } ::ParseImageNtHeader( - *m_stream, m_imageDosHeader, m_imageNtHeader, m_imageOptionalHeaders32, m_imageOptionalHeaders64, ec); + m_stream, m_imageDosHeader, m_imageNtHeader, m_imageOptionalHeaders32, m_imageOptionalHeaders64, ec); if (ec) { return; } - ::ParseImageSections(*m_stream, m_imageNtHeader, m_imageSectionsHeaders, ec); + ::ParseImageSections(m_stream, m_imageNtHeader, m_imageSectionsHeaders, ec); if (ec) { return; @@ -313,7 +313,7 @@ void PeParser::ReadDirectory(uint8_t index, std::vector& buffer, std::e } buffer.resize(directory.Size); - ReadChunkAt(*m_stream, directory.VirtualAddress, buffer, ec); + ReadChunkAt(m_stream, directory.VirtualAddress, buffer, ec); if (ec) { Log::Debug("Failed to read directory (index: {}) [{}]", index, ec); @@ -403,7 +403,7 @@ void PeParser::GetHashedChunks(PeChunks& chunks, std::error_code& ec) const } chunks[3].offset = GetSizeOfOptionalHeaders(); - chunks[3].length = m_stream->GetSize() - chunks[3].offset - secdir.Size; + chunks[3].length = m_stream.GetSize() - chunks[3].offset - secdir.Size; } void PeParser::Hash(CryptoHashStreamAlgorithm algorithms, const PeChunks& chunks, PeHash& output, std::error_code& ec) @@ -418,7 +418,7 @@ void PeParser::Hash(CryptoHashStreamAlgorithm algorithms, const PeChunks& chunks return; } - const auto written = ::CopyChunks(chunks, *m_stream, *hashstream, ec); + const auto written = ::CopyChunks(chunks, m_stream, *hashstream, ec); if (ec) { Log::Debug("Failed to hash chunks [{}]", ec); @@ -427,7 +427,7 @@ void PeParser::Hash(CryptoHashStreamAlgorithm algorithms, const PeChunks& chunks // MS does zero padding for PEs that are not 8 modulo (often with catalogs) const uint8_t padding[8] = {0, 0, 0, 0, 0, 0, 0, 0}; - const auto alignment = m_stream->GetSize() % sizeof(padding); + const auto alignment = m_stream.GetSize() % sizeof(padding); if (alignment != 0) { const auto paddingLength = sizeof(padding) - alignment; diff --git a/src/OrcLib/FileFormat/PeParser.h b/src/OrcLib/FileFormat/PeParser.h index c94af461..8ace0184 100644 --- a/src/OrcLib/FileFormat/PeParser.h +++ b/src/OrcLib/FileFormat/PeParser.h @@ -44,7 +44,7 @@ class PeParser using PeChunks = std::array; using SectionHeaders = fmt::basic_memory_buffer; - PeParser(std::shared_ptr stream, std::error_code& ec); + PeParser(ByteStream& stream, std::error_code& ec); bool HasDebugDirectory() const; void ReadDebugDirectory(std::vector& buffer, std::error_code& ec) const; @@ -66,7 +66,7 @@ class PeParser void Hash(CryptoHashStreamAlgorithm algorithms, const PeChunks& chunks, PeHash& output, std::error_code& ec) const; private: - mutable std::shared_ptr m_stream; + ByteStream& m_stream; IMAGE_DOS_HEADER m_imageDosHeader; ImageNtHeader m_imageNtHeader; std::optional m_imageOptionalHeaders32; diff --git a/src/OrcLib/PEInfo.cpp b/src/OrcLib/PEInfo.cpp index 72a8cfe6..c3a285fa 100644 --- a/src/OrcLib/PEInfo.cpp +++ b/src/OrcLib/PEInfo.cpp @@ -307,7 +307,7 @@ HRESULT PEInfo::OpenVersionInformation() return E_POINTER; } - auto stream = std::make_shared(directStream, 4096); + auto stream = std::make_shared(*directStream, 4096); ULONGLONG ullBytesRead; size_t rsrc_rsrc_offset = 0; @@ -648,7 +648,7 @@ HRESULT PEInfo::OpenAllHash(Intentions localIntentions) // Pe Hash { std::error_code ec; - PeParser pe(memstream, ec); + PeParser pe(*memstream, ec); if (ec) { Log::Debug(L"Failed to parse pe hash '{}' [{}]", m_FileInfo.m_szFullName, ec); @@ -723,7 +723,8 @@ HRESULT PEInfo::OpenPeHash(Intentions localIntentions) return E_POINTER; std::error_code ec; - PeParser pe(std::make_shared(std::move(stream)), ec); + CacheStream cache(*stream, 1048576); + PeParser pe(cache, ec); if (ec) { Log::Error(L"Failed to parse PE '{}' [{}]", m_FileInfo.m_szFullName, ec); From f2a188acaf1133ff556d6e47143466f725965cff Mon Sep 17 00:00:00 2001 From: fabienfl Date: Fri, 8 Mar 2024 16:08:27 +0100 Subject: [PATCH 09/60] OrcLib: CacheStream: add Guard::CacheStream --- src/OrcLib/CacheStream.h | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/src/OrcLib/CacheStream.h b/src/OrcLib/CacheStream.h index 3f2b8d10..ab1fd06f 100644 --- a/src/OrcLib/CacheStream.h +++ b/src/OrcLib/CacheStream.h @@ -68,6 +68,24 @@ class CacheStream : public ByteStream uint64_t m_cacheOffset; }; +namespace Guard { + +template +class CacheStream final : public Orc::CacheStream +{ +public: + CacheStream(StreamT stream, size_t cache_size) + : CacheStream(*MetaPtr(stream).get(), cache_size) + , m_stream(std::move(stream)) + { + } + +private: + MetaPtr m_stream; +}; + +} // namespace Guard + } // namespace Orc #pragma managed(pop) From 0e154034a472286b3b18c03b1673f762a5343f0f Mon Sep 17 00:00:00 2001 From: fabienfl Date: Fri, 8 Mar 2024 16:33:30 +0100 Subject: [PATCH 10/60] OrcLib: CacheStream: fix SetFilePointer when getting seek position --- src/OrcLib/CacheStream.cpp | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/OrcLib/CacheStream.cpp b/src/OrcLib/CacheStream.cpp index 9f1c422f..5001385f 100644 --- a/src/OrcLib/CacheStream.cpp +++ b/src/OrcLib/CacheStream.cpp @@ -149,6 +149,18 @@ CacheStream::SetFilePointer(__in LONGLONG DistanceToMove, __in DWORD dwMoveMetho pCurrPointer = &newOffset; } + if (dwMoveMethod == FILE_CURRENT) + { + if (DistanceToMove == 0) + { + *pCurrPointer = m_offset; + return S_OK; + } + + dwMoveMethod = FILE_BEGIN; + DistanceToMove = m_offset + DistanceToMove; + } + HRESULT hr = m_stream.SetFilePointer(DistanceToMove, dwMoveMethod, pCurrPointer); if (FAILED(hr)) { From 00963e34b79cfe6490d3d09d697c2ca0a4bd0d95 Mon Sep 17 00:00:00 2001 From: fabienfl Date: Wed, 24 Apr 2024 08:31:58 +0200 Subject: [PATCH 11/60] OrcLib: Text: Fmt: make const specialization for std::filesystem --- src/OrcLib/Text/Fmt/std_filesystem.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/OrcLib/Text/Fmt/std_filesystem.h b/src/OrcLib/Text/Fmt/std_filesystem.h index 15a64c8e..fee2f966 100644 --- a/src/OrcLib/Text/Fmt/std_filesystem.h +++ b/src/OrcLib/Text/Fmt/std_filesystem.h @@ -17,7 +17,7 @@ template <> struct fmt::formatter : public fmt::formatter { template - auto format(const std::filesystem::path& path, FormatContext& ctx) + auto format(const std::filesystem::path& path, FormatContext& ctx) const { return fmt::formatter::format(path.string(), ctx); } @@ -27,7 +27,7 @@ template <> struct fmt::formatter : public fmt::formatter { template - auto format(const std::filesystem::path& path, FormatContext& ctx) + auto format(const std::filesystem::path& path, FormatContext& ctx) const { return fmt::formatter::format(path.wstring(), ctx); } From 476ed665a4ebbe61d20ebd9373fc22c477dbb843 Mon Sep 17 00:00:00 2001 From: fabienfl Date: Mon, 29 Apr 2024 11:44:20 +0200 Subject: [PATCH 12/60] OrcCommand: UtilitiesMain: enhance printed parameter name --- src/OrcCommand/UtilitiesMain.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/OrcCommand/UtilitiesMain.cpp b/src/OrcCommand/UtilitiesMain.cpp index 65fbf031..cff4468c 100644 --- a/src/OrcCommand/UtilitiesMain.cpp +++ b/src/OrcCommand/UtilitiesMain.cpp @@ -64,7 +64,7 @@ void UtilitiesMain::PrintCommonParameters(Orc::Text::Tree& root) SystemDetails::GetOrcFullComputerName(orcFullComputerName); if (orcFullComputerName != fullComputerName && orcFullComputerName != orcComputerName) { - PrintValue(root, L"DFIR-Orc computer", orcFullComputerName); + PrintValue(root, L"DFIR-Orc full computer name", orcFullComputerName); } std::wstring description; From 6e3b793fc35b816c50ed903d1f648739a091cd49 Mon Sep 17 00:00:00 2001 From: fabienfl Date: Mon, 29 Apr 2024 11:52:26 +0200 Subject: [PATCH 13/60] OrcCommand: WolfLauncher: Outline: set outline.computer_name with /FullComputer Or fallback on /Computer then host's. --- src/OrcCommand/Command/WolfLauncher/WolfLauncher_Run.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/OrcCommand/Command/WolfLauncher/WolfLauncher_Run.cpp b/src/OrcCommand/Command/WolfLauncher/WolfLauncher_Run.cpp index 33429ffa..4ebb1eb9 100644 --- a/src/OrcCommand/Command/WolfLauncher/WolfLauncher_Run.cpp +++ b/src/OrcCommand/Command/WolfLauncher/WolfLauncher_Run.cpp @@ -595,7 +595,7 @@ HRESULT Orc::Command::Wolf::Main::CreateAndUploadOutline() { std::wstring computerName; - SystemDetails::GetFullComputerName(computerName); + SystemDetails::GetOrcFullComputerName(computerName); writer->WriteNamed(L"computer_name", computerName); } From 30224e5ac356793a5b6296baf929ce11538271c3 Mon Sep 17 00:00:00 2001 From: fabienfl Date: Mon, 29 Apr 2024 11:49:35 +0200 Subject: [PATCH 14/60] OrcCommand: WolfLauncher: Outcome: set outcome.computer_name with /FullComputer Or fallback on /Computer then host's. --- src/OrcCommand/Command/WolfLauncher/Outcome.cpp | 2 +- src/OrcCommand/Command/WolfLauncher/Outcome.h | 4 ++++ src/OrcCommand/Command/WolfLauncher/WolfLauncher_Run.cpp | 6 ++++++ 3 files changed, 11 insertions(+), 1 deletion(-) diff --git a/src/OrcCommand/Command/WolfLauncher/Outcome.cpp b/src/OrcCommand/Command/WolfLauncher/Outcome.cpp index 4e940c08..f0ec34af 100644 --- a/src/OrcCommand/Command/WolfLauncher/Outcome.cpp +++ b/src/OrcCommand/Command/WolfLauncher/Outcome.cpp @@ -375,7 +375,7 @@ Orc::Result Write(const Outcome& outcome, StructuredOutputWriter::IWriter: writer->WriteNamed(L"end", *endingTime); } - writer->WriteNamed(L"computer_name", outcome.GetComputerNameValue()); + writer->WriteNamed(L"computer_name", outcome.GetOrcComputerNameValue()); ::Write(writer, outcome.GetMothership()); diff --git a/src/OrcCommand/Command/WolfLauncher/Outcome.h b/src/OrcCommand/Command/WolfLauncher/Outcome.h index ca9544b1..d31f39f9 100644 --- a/src/OrcCommand/Command/WolfLauncher/Outcome.h +++ b/src/OrcCommand/Command/WolfLauncher/Outcome.h @@ -407,6 +407,9 @@ class Outcome const std::wstring& GetComputerNameValue() const { return m_computerName; } void SetComputerNameValue(std::wstring name) { m_computerName = std::move(name); } + const std::wstring& GetOrcComputerNameValue() const { return m_orcComputerName; } + void SetOrcComputerNameValue(std::wstring name) { m_orcComputerName = std::move(name); } + // Timestamp is used as a unique identifier between orc execution and multiple files std::wstring GetTimestampKey() const { return m_timestamp; } void SetTimestampKey(const std::wstring& timestamp) { m_timestamp = timestamp; } @@ -439,6 +442,7 @@ class Outcome mutable std::mutex m_mutex; GUID m_id; std::wstring m_computerName; + std::wstring m_orcComputerName; Mothership m_mothership; std::wstring m_consoleFileName; std::wstring m_logFileName; diff --git a/src/OrcCommand/Command/WolfLauncher/WolfLauncher_Run.cpp b/src/OrcCommand/Command/WolfLauncher/WolfLauncher_Run.cpp index 4ebb1eb9..8f6b5713 100644 --- a/src/OrcCommand/Command/WolfLauncher/WolfLauncher_Run.cpp +++ b/src/OrcCommand/Command/WolfLauncher/WolfLauncher_Run.cpp @@ -227,6 +227,12 @@ void UpdateOutcome(Command::Wolf::Outcome::Outcome& outcome, const GUID& id, HAN outcome.SetComputerNameValue(computerName); } + { + std::wstring orcComputerName; + SystemDetails::GetOrcFullComputerName(orcComputerName); + outcome.SetOrcComputerNameValue(orcComputerName); + } + { std::wstring timestampKey; HRESULT hr = SystemDetails::GetTimeStamp(timestampKey); From 41346e573b8d43a35e68f2483b051f8b0caea71e Mon Sep 17 00:00:00 2001 From: fabienfl Date: Mon, 29 Apr 2024 11:53:53 +0200 Subject: [PATCH 15/60] OrcCommand: WolfLauncher: set outline.system[full]name with host's --- src/OrcLib/SystemIdentity.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/OrcLib/SystemIdentity.cpp b/src/OrcLib/SystemIdentity.cpp index be31a427..e8bc5aa9 100644 --- a/src/OrcLib/SystemIdentity.cpp +++ b/src/OrcLib/SystemIdentity.cpp @@ -166,12 +166,12 @@ HRESULT Orc::SystemIdentity::System(const std::shared_ptrWriteNamed(L"name", strComputerName.c_str()); } { std::wstring strFullComputerName; - SystemDetails::GetOrcFullComputerName(strFullComputerName); + SystemDetails::GetFullComputerName(strFullComputerName); writer->WriteNamed(L"fullname", strFullComputerName.c_str()); } { From 69f96b0deded758fb0ab4356ffee7b24b8c4f53e Mon Sep 17 00:00:00 2001 From: fabienfl Date: Mon, 29 Apr 2024 11:56:44 +0200 Subject: [PATCH 16/60] OrcLib: SystemDetail: add GetOrcSystemType It stores the user's specified value and fallback on host's --- .../Command/FastFind/FastFind_Run.cpp | 2 +- .../WolfLauncher/WolfExecution_Config.cpp | 2 +- src/OrcCommand/UtilitiesMain.cpp | 6 ++++- src/OrcLib/CommandAgent.cpp | 2 +- src/OrcLib/OutputSpec.cpp | 2 +- src/OrcLib/SystemDetails.cpp | 27 +++++++++++++++++++ src/OrcLib/SystemDetails.h | 3 +++ 7 files changed, 39 insertions(+), 5 deletions(-) diff --git a/src/OrcCommand/Command/FastFind/FastFind_Run.cpp b/src/OrcCommand/Command/FastFind/FastFind_Run.cpp index 58d8988b..177383c2 100644 --- a/src/OrcCommand/Command/FastFind/FastFind_Run.cpp +++ b/src/OrcCommand/Command/FastFind/FastFind_Run.cpp @@ -671,7 +671,7 @@ HRESULT Main::Run() pStructuredOutput->WriteNamed(L"os", strSystemDescr.c_str()); std::wstring strSystemRole; - if (SUCCEEDED(SystemDetails::GetSystemType(strSystemRole))) + if (SUCCEEDED(SystemDetails::GetOrcSystemType(strSystemRole))) pStructuredOutput->WriteNamed(L"role", strSystemRole.c_str()); } diff --git a/src/OrcCommand/Command/WolfLauncher/WolfExecution_Config.cpp b/src/OrcCommand/Command/WolfLauncher/WolfExecution_Config.cpp index c7e68d24..84aae27a 100644 --- a/src/OrcCommand/Command/WolfLauncher/WolfExecution_Config.cpp +++ b/src/OrcCommand/Command/WolfLauncher/WolfExecution_Config.cpp @@ -266,7 +266,7 @@ CommandMessage::Message WolfExecution::SetCommandFromConfigItem(const ConfigItem const wstring& requiredSystemTypes = item[WOLFLAUNCHER_COMMAND_SYSTEMTYPE]; wstring strProductType; - if (FAILED(hr = SystemDetails::GetSystemType(strProductType))) + if (FAILED(hr = SystemDetails::GetOrcSystemType(strProductType))) { Log::Error("Failed to retrieve system product type [{}]", SystemError(hr)); return nullptr; diff --git a/src/OrcCommand/UtilitiesMain.cpp b/src/OrcCommand/UtilitiesMain.cpp index cff4468c..359a525d 100644 --- a/src/OrcCommand/UtilitiesMain.cpp +++ b/src/OrcCommand/UtilitiesMain.cpp @@ -81,6 +81,10 @@ void UtilitiesMain::PrintCommonParameters(Orc::Text::Tree& root) SystemDetails::GetSystemType(systemType); PrintValue(root, L"System type", systemType); + std::wstring orcSystemType; + SystemDetails::GetOrcSystemType(orcSystemType); + PrintValue(root, L"DFIR-Orc system type", orcSystemType); + PrintValue(root, L"System tags", boost::join(SystemDetails::GetSystemTags(), ", ")); std::wstring logFileName(Text::kEmptyW); @@ -223,7 +227,7 @@ void UtilitiesMain::Configure(int argc, const wchar_t* argv[]) if (!systemType.empty()) { - SystemDetails::SetSystemType(systemType); + SystemDetails::SetOrcSystemType(systemType); } } diff --git a/src/OrcLib/CommandAgent.cpp b/src/OrcLib/CommandAgent.cpp index 2f24c9e8..8ca1dd45 100644 --- a/src/OrcLib/CommandAgent.cpp +++ b/src/OrcLib/CommandAgent.cpp @@ -273,7 +273,7 @@ HRESULT CommandAgent::ApplyPattern( auto s6 = std::regex_replace(s5, r_TimeStamp, strTimeStamp); wstring strSystemType; - SystemDetails::GetSystemType(strSystemType); + SystemDetails::GetOrcSystemType(strSystemType); auto s7 = std::regex_replace(s6, r_SystemType, strSystemType); std::swap(s7, output); diff --git a/src/OrcLib/OutputSpec.cpp b/src/OrcLib/OutputSpec.cpp index a918a139..52b8eb48 100644 --- a/src/OrcLib/OutputSpec.cpp +++ b/src/OrcLib/OutputSpec.cpp @@ -86,7 +86,7 @@ OutputSpec::ApplyPattern(const std::wstring& strPattern, const std::wstring& str SystemDetails::GetTimeStamp(strTimeStamp); wstring strSystemType; - SystemDetails::GetSystemType(strSystemType); + SystemDetails::GetOrcSystemType(strSystemType); strFileName = fmt::vformat( fmt::wstring_view(strPattern), diff --git a/src/OrcLib/SystemDetails.cpp b/src/OrcLib/SystemDetails.cpp index 57b755ff..62db7c2c 100644 --- a/src/OrcLib/SystemDetails.cpp +++ b/src/OrcLib/SystemDetails.cpp @@ -46,6 +46,7 @@ struct SystemDetailsBlock std::optional strOrcComputerName; std::optional strOrcFullComputerName; std::optional strProductType; + std::optional strOrcProductType; std::optional wProductType; std::wstring strUserName; std::wstring strUserSID; @@ -105,6 +106,32 @@ HRESULT SystemDetails::GetSystemType(std::wstring& strProductType) return S_OK; } +HRESULT Orc::SystemDetails::SetOrcSystemType(std::wstring strProductType) +{ + HRESULT hr = E_FAIL; + if (FAILED(hr = LoadSystemDetails())) + return hr; + + if (!strProductType.empty()) + g_pDetailsBlock->strOrcProductType.emplace(std::move(strProductType)); + + return S_OK; +} + +HRESULT SystemDetails::GetOrcSystemType(std::wstring& strProductType) +{ + HRESULT hr = E_FAIL; + if (FAILED(hr = LoadSystemDetails())) + return hr; + + if (g_pDetailsBlock->strOrcProductType.has_value()) + { + strProductType = g_pDetailsBlock->strOrcProductType.value(); + return S_OK; + } + + return GetSystemType(strProductType); +} bool SystemDetails::IsKnownWindowsBuild(uint32_t build) { diff --git a/src/OrcLib/SystemDetails.h b/src/OrcLib/SystemDetails.h index 16f56500..62861a08 100644 --- a/src/OrcLib/SystemDetails.h +++ b/src/OrcLib/SystemDetails.h @@ -45,6 +45,9 @@ class SystemDetails static HRESULT GetSystemType(std::wstring& strSystemType); static HRESULT GetSystemType(BYTE& systemType); + static HRESULT SetOrcSystemType(std::wstring strSystemType); + static HRESULT GetOrcSystemType(std::wstring& strSystemType); + static bool IsKnownWindowsBuild(uint32_t build); static void GetTagsFromBuildId(uint32_t ProductType, uint32_t build, SystemTags& tags); From 7e5242639e1a300a6e24449adbfaffdb81c8d9d9 Mon Sep 17 00:00:00 2001 From: fabienfl Date: Mon, 29 Apr 2024 11:57:49 +0200 Subject: [PATCH 17/60] OrcCommand: WolfLauncher: Outline: add outline.system_type --- src/OrcCommand/Command/WolfLauncher/WolfLauncher_Run.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/OrcCommand/Command/WolfLauncher/WolfLauncher_Run.cpp b/src/OrcCommand/Command/WolfLauncher/WolfLauncher_Run.cpp index 8f6b5713..3476dcc8 100644 --- a/src/OrcCommand/Command/WolfLauncher/WolfLauncher_Run.cpp +++ b/src/OrcCommand/Command/WolfLauncher/WolfLauncher_Run.cpp @@ -605,6 +605,12 @@ HRESULT Orc::Command::Wolf::Main::CreateAndUploadOutline() writer->WriteNamed(L"computer_name", computerName); } + { + std::wstring systemType; + SystemDetails::GetOrcSystemType(systemType); + writer->WriteNamed(L"system_type", systemType); + } + auto mothership_id = SystemDetails::GetParentProcessId(); if (mothership_id) { From 5e9b0b25e4ac1446d803a3ae64dd323ee6994bcd Mon Sep 17 00:00:00 2001 From: fabienfl Date: Mon, 29 Apr 2024 11:57:35 +0200 Subject: [PATCH 18/60] OrcCommand: WolfLauncher: Outcome: add outcome.system_type --- src/OrcCommand/Command/WolfLauncher/Outcome.cpp | 2 +- src/OrcCommand/Command/WolfLauncher/Outcome.h | 4 ++++ src/OrcCommand/Command/WolfLauncher/WolfLauncher_Run.cpp | 6 ++++++ 3 files changed, 11 insertions(+), 1 deletion(-) diff --git a/src/OrcCommand/Command/WolfLauncher/Outcome.cpp b/src/OrcCommand/Command/WolfLauncher/Outcome.cpp index f0ec34af..3801dc5d 100644 --- a/src/OrcCommand/Command/WolfLauncher/Outcome.cpp +++ b/src/OrcCommand/Command/WolfLauncher/Outcome.cpp @@ -376,9 +376,9 @@ Orc::Result Write(const Outcome& outcome, StructuredOutputWriter::IWriter: } writer->WriteNamed(L"computer_name", outcome.GetOrcComputerNameValue()); + writer->WriteNamed(L"system_type", outcome.GetOrcSystemTypeValue()); ::Write(writer, outcome.GetMothership()); - ::Write(writer, outcome.GetWolfLauncher()); { diff --git a/src/OrcCommand/Command/WolfLauncher/Outcome.h b/src/OrcCommand/Command/WolfLauncher/Outcome.h index d31f39f9..ff81ec67 100644 --- a/src/OrcCommand/Command/WolfLauncher/Outcome.h +++ b/src/OrcCommand/Command/WolfLauncher/Outcome.h @@ -410,6 +410,9 @@ class Outcome const std::wstring& GetOrcComputerNameValue() const { return m_orcComputerName; } void SetOrcComputerNameValue(std::wstring name) { m_orcComputerName = std::move(name); } + const std::wstring& GetOrcSystemTypeValue() const { return m_orcSystemType; } + void SetOrcSystemTypeValue(std::wstring type) { m_orcSystemType = std::move(type); } + // Timestamp is used as a unique identifier between orc execution and multiple files std::wstring GetTimestampKey() const { return m_timestamp; } void SetTimestampKey(const std::wstring& timestamp) { m_timestamp = timestamp; } @@ -443,6 +446,7 @@ class Outcome GUID m_id; std::wstring m_computerName; std::wstring m_orcComputerName; + std::wstring m_orcSystemType; Mothership m_mothership; std::wstring m_consoleFileName; std::wstring m_logFileName; diff --git a/src/OrcCommand/Command/WolfLauncher/WolfLauncher_Run.cpp b/src/OrcCommand/Command/WolfLauncher/WolfLauncher_Run.cpp index 3476dcc8..31ec1656 100644 --- a/src/OrcCommand/Command/WolfLauncher/WolfLauncher_Run.cpp +++ b/src/OrcCommand/Command/WolfLauncher/WolfLauncher_Run.cpp @@ -233,6 +233,12 @@ void UpdateOutcome(Command::Wolf::Outcome::Outcome& outcome, const GUID& id, HAN outcome.SetOrcComputerNameValue(orcComputerName); } + { + std::wstring orcSystemType; + SystemDetails::GetOrcSystemType(orcSystemType); + outcome.SetOrcSystemTypeValue(orcSystemType); + } + { std::wstring timestampKey; HRESULT hr = SystemDetails::GetTimeStamp(timestampKey); From 0d146fd04ec7d87b82fc20e9e6d990a08047b2bc Mon Sep 17 00:00:00 2001 From: fabienfl Date: Mon, 29 Apr 2024 13:58:43 +0200 Subject: [PATCH 19/60] OrcCommand: WolfLauncher: Outcome: replace 'running_command' with 'live' --- src/OrcCommand/Command/WolfLauncher/Outcome.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/OrcCommand/Command/WolfLauncher/Outcome.cpp b/src/OrcCommand/Command/WolfLauncher/Outcome.cpp index 3801dc5d..4b812c55 100644 --- a/src/OrcCommand/Command/WolfLauncher/Outcome.cpp +++ b/src/OrcCommand/Command/WolfLauncher/Outcome.cpp @@ -149,7 +149,7 @@ std::string ToString(Outcome::Archive::InputType inputType) case Outcome::Archive::InputType::kOffline: return "offline"; case Outcome::Archive::InputType::kRunningSystem: - return "running_system"; + return "live"; } return ""; From efba8ab309951dceaa33bedecc435c64613f6964 Mon Sep 17 00:00:00 2001 From: fabienfl Date: Mon, 29 Apr 2024 17:28:57 +0200 Subject: [PATCH 20/60] OrcLib: SystemDetail: add GetCodePage and GetCodePageName --- src/OrcLib/SystemDetails.cpp | 48 ++++++++++++++++++++++++++++++++++-- src/OrcLib/SystemDetails.h | 3 +++ 2 files changed, 49 insertions(+), 2 deletions(-) diff --git a/src/OrcLib/SystemDetails.cpp b/src/OrcLib/SystemDetails.cpp index 62db7c2c..9373e431 100644 --- a/src/OrcLib/SystemDetails.cpp +++ b/src/OrcLib/SystemDetails.cpp @@ -19,6 +19,7 @@ #include #include +#include #include "TableOutput.h" #include "WideAnsi.h" @@ -32,6 +33,19 @@ namespace fs = std::filesystem; using namespace std::string_view_literals; using namespace Orc; +namespace { + +template +inline void CopyUntil(_InIt _First, _InIt _Last, _OutIt _Dest, _Pr _Pred) +{ + while ((_First != _Last) && _Pred(*_First)) + { + *_Dest++ = *_First++; + } +} + +} // namespace + namespace Orc { struct SystemDetailsBlock { @@ -178,8 +192,7 @@ void SystemDetails::GetTagsFromBuildId(uint32_t ProductType, uint32_t build, Sys if (ProductType != VER_NT_WORKSTATION && ProductType != VER_NT_SERVER && ProductType != VER_NT_DOMAIN_CONTROLLER) { - Log::Warn( - L"ProductType {} is out of valid values range, we \"reset\" it to VER_NT_WORKSTATION", ProductType); + Log::Warn(L"ProductType {} is out of valid values range, we \"reset\" it to VER_NT_WORKSTATION", ProductType); ProductType = VER_NT_WORKSTATION; } @@ -1035,6 +1048,37 @@ HRESULT Orc::SystemDetails::GetUserLanguage(std::wstring& strLanguage) return S_OK; } +Result Orc::SystemDetails::GetCodePageName() +{ + CPINFOEXW info = {0}; + BOOL rv = GetCPInfoExW(GetConsoleOutputCP(), 0, &info); + if (!rv) + { + auto ec = LastWin32Error(); + Log::Debug("Failed GetCPInfoExW [{}]", ec); + return ec; + } + + std::wstring_view buffer {info.CodePageName, sizeof(info.CodePageName) / sizeof(wchar_t)}; + std::wstring name; + CopyUntil(std::cbegin(buffer), std::cend(buffer), std::back_inserter(name), [](auto c) { return std::isprint(c); }); + return name; +} + +Result Orc::SystemDetails::GetCodePage() +{ + CPINFOEXW info = {0}; + BOOL rv = GetCPInfoExW(GetConsoleOutputCP(), 0, &info); + if (!rv) + { + auto ec = LastWin32Error(); + Log::Debug("Failed GetCPInfoExW [{}]", ec); + return ec; + } + + return info.CodePage; +} + Result Orc::SystemDetails::GetShutdownTimeFromRegistry() { const wchar_t key[] = L"SYSTEM\\CurrentControlSet\\Control\\Windows"; diff --git a/src/OrcLib/SystemDetails.h b/src/OrcLib/SystemDetails.h index 62861a08..ffcb37eb 100644 --- a/src/OrcLib/SystemDetails.h +++ b/src/OrcLib/SystemDetails.h @@ -117,6 +117,9 @@ class SystemDetails static HRESULT GetSystemLanguage(std::wstring& strLocale); static HRESULT GetUserLanguage(std::wstring& strLocale); + static Result GetCodePageName(); + static Result GetCodePage(); + static Result GetShutdownTimeFromRegistry(); static Result GetInstallTimeFromRegistry(); static Result GetInstallDateFromRegistry(); From be0c2613ec82b78beef1cfceb224451528bf39d6 Mon Sep 17 00:00:00 2001 From: fabienfl Date: Mon, 29 Apr 2024 17:29:30 +0200 Subject: [PATCH 21/60] OrcLib: SystemIdentity: add to codepage information to Outline --- src/OrcLib/SystemIdentity.cpp | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/src/OrcLib/SystemIdentity.cpp b/src/OrcLib/SystemIdentity.cpp index e8bc5aa9..792d4443 100644 --- a/src/OrcLib/SystemIdentity.cpp +++ b/src/OrcLib/SystemIdentity.cpp @@ -179,6 +179,21 @@ HRESULT Orc::SystemIdentity::System(const std::shared_ptrWriteNamed(L"type", strSystemType.c_str()); } + + { + auto codepage = SystemDetails::GetCodePage(); + if (codepage) + { + writer->WriteNamed(L"codepage", *codepage); + } + + auto codepage_name = SystemDetails::GetCodePageName(); + if (codepage_name) + { + writer->WriteNamed(L"codepage_name", *codepage_name); + } + } + { WORD wArch = 0; SystemDetails::GetArchitecture(wArch); From ecc914bca444bbb44301ca3327d0381382339f06 Mon Sep 17 00:00:00 2001 From: fabienfl Date: Tue, 30 Apr 2024 10:51:21 +0200 Subject: [PATCH 22/60] OrcCommand: WolfLauncher: Outline: add commands timeout --- .../Command/WolfLauncher/WolfLauncher_Run.cpp | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/src/OrcCommand/Command/WolfLauncher/WolfLauncher_Run.cpp b/src/OrcCommand/Command/WolfLauncher/WolfLauncher_Run.cpp index 31ec1656..7abe56ce 100644 --- a/src/OrcCommand/Command/WolfLauncher/WolfLauncher_Run.cpp +++ b/src/OrcCommand/Command/WolfLauncher/WolfLauncher_Run.cpp @@ -689,7 +689,17 @@ HRESULT Orc::Command::Wolf::Main::CreateAndUploadOutline() { if (!command->IsOptional()) { - writer->Write(command->Keyword().c_str()); + writer->BeginElement(nullptr); + writer->WriteNamed(L"name", command->Keyword().c_str()); + + if (command->GetTimeout()) + { + std::chrono::milliseconds timeout = command->GetTimeout().value(); + writer->WriteNamed( + L"timeout", std::chrono::duration_cast(timeout).count()); + } + + writer->EndElement(nullptr); } } writer->EndCollection(L"commands"); From 067ada7c42f6a569ed554c86cb4f32802a6338ca Mon Sep 17 00:00:00 2001 From: fabienfl Date: Tue, 30 Apr 2024 13:59:44 +0200 Subject: [PATCH 23/60] OrcCommand: WolfLauncher: Outline: add commands output files --- .../Command/WolfLauncher/WolfLauncher_Run.cpp | 38 +++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/src/OrcCommand/Command/WolfLauncher/WolfLauncher_Run.cpp b/src/OrcCommand/Command/WolfLauncher/WolfLauncher_Run.cpp index 7abe56ce..ac301e16 100644 --- a/src/OrcCommand/Command/WolfLauncher/WolfLauncher_Run.cpp +++ b/src/OrcCommand/Command/WolfLauncher/WolfLauncher_Run.cpp @@ -374,6 +374,25 @@ Orc::Result DumpOutcome(Command::Wolf::Outcome::Outcome& outcome, const Ou return Orc::Success(); } +std::wstring ToSourceString(CommandParameter::ParamKind kind) +{ + switch (kind) + { + case CommandParameter::ParamKind::OutFile: + return L"file"; + case CommandParameter::ParamKind::OutDirectory: + return L"directory"; + case CommandParameter::ParamKind::StdErr: + return L"stderr"; + case CommandParameter::ParamKind::StdOut: + return L"stderr"; + case CommandParameter::ParamKind::StdOutErr: + return L"stdouterr"; + default: + return L""; + } +} + } // namespace namespace Orc { @@ -697,6 +716,25 @@ HRESULT Orc::Command::Wolf::Main::CreateAndUploadOutline() std::chrono::milliseconds timeout = command->GetTimeout().value(); writer->WriteNamed( L"timeout", std::chrono::duration_cast(timeout).count()); + + writer->BeginCollection(L"output"); + + for (const auto& parameter : command->GetParameters()) + { + if (parameter.Kind == CommandParameter::OutFile + || parameter.Kind == CommandParameter::OutDirectory + || parameter.Kind == CommandParameter::StdOut + || parameter.Kind == CommandParameter::StdErr + || parameter.Kind == CommandParameter::StdOutErr) + { + writer->BeginElement(nullptr); + writer->WriteNamed(L"name", parameter.Name); + writer->WriteNamed(L"source", ToSourceString(parameter.Kind)); + writer->EndElement(nullptr); + } + } + + writer->EndCollection(L"output"); } writer->EndElement(nullptr); From 352ca617169003910e9c8e2075db8cb27e079fa3 Mon Sep 17 00:00:00 2001 From: fabienfl Date: Tue, 30 Apr 2024 14:33:51 +0200 Subject: [PATCH 24/60] OrcCommand: WolfLauncher: display run id in the parameter dump and log --- src/OrcCommand/Command/WolfLauncher/WolfLauncher.h | 1 - .../Command/WolfLauncher/WolfLauncher_Config.cpp | 10 +++++++--- .../Command/WolfLauncher/WolfLauncher_Output.cpp | 2 ++ .../Command/WolfLauncher/WolfLauncher_Run.cpp | 6 ++---- src/OrcLib/SystemDetails.cpp | 11 +++++++++++ src/OrcLib/SystemDetails.h | 3 +++ 6 files changed, 25 insertions(+), 8 deletions(-) diff --git a/src/OrcCommand/Command/WolfLauncher/WolfLauncher.h b/src/OrcCommand/Command/WolfLauncher/WolfLauncher.h index da3e9e4d..a4d1fb48 100644 --- a/src/OrcCommand/Command/WolfLauncher/WolfLauncher.h +++ b/src/OrcCommand/Command/WolfLauncher/WolfLauncher.h @@ -215,7 +215,6 @@ class ORCUTILS_API Main : public UtilitiesMain void ReadLogConfiguration(const ConfigItem& configItem, bool hasConsoleConfigItem); private: - GUID m_guid; ConsoleConfiguration m_consoleConfiguration; Journal m_journal; diff --git a/src/OrcCommand/Command/WolfLauncher/WolfLauncher_Config.cpp b/src/OrcCommand/Command/WolfLauncher/WolfLauncher_Config.cpp index 8601deda..5dd5d2e6 100644 --- a/src/OrcCommand/Command/WolfLauncher/WolfLauncher_Config.cpp +++ b/src/OrcCommand/Command/WolfLauncher/WolfLauncher_Config.cpp @@ -774,14 +774,18 @@ HRESULT Main::CheckConfiguration() { HRESULT hr = E_FAIL; - hr = CoCreateGuid(&m_guid); + GUID guid; + hr = CoCreateGuid(&guid); if (FAILED(hr)) { Log::Error("Failed to initialize execution guid [{}]", SystemError(hr)); - SecureZeroMemory(&m_guid, sizeof(m_guid)); + SecureZeroMemory(&guid, sizeof(guid)); hr = S_OK; // keep going } + SystemDetails::SetOrcRunId(guid); + Log::Debug(L"Starting DFIR-Orc (run id: {})", ToStringW(guid)); + if (m_consoleConfiguration.output.path) { m_consoleConfiguration.output.path = @@ -799,7 +803,7 @@ HRESULT Main::CheckConfiguration() if (m_utilitiesConfig.log.logFile) { - // Deprecated: 10.0.x compatilbility options + // Deprecated: 10.0.x compatibility options // Apply the output directory path to the log file logPath = fs::path(config.Output.Path) / fs::path(*m_utilitiesConfig.log.logFile).filename(); m_utilitiesConfig.log.logFile = logPath; diff --git a/src/OrcCommand/Command/WolfLauncher/WolfLauncher_Output.cpp b/src/OrcCommand/Command/WolfLauncher/WolfLauncher_Output.cpp index fd5dfaeb..bd142ead 100644 --- a/src/OrcCommand/Command/WolfLauncher/WolfLauncher_Output.cpp +++ b/src/OrcCommand/Command/WolfLauncher/WolfLauncher_Output.cpp @@ -169,6 +169,8 @@ void Main::PrintParameters() PrintCommonParameters(node); + PrintValue(node, L"Run ID", ToStringW(SystemDetails::GetOrcRunId())); + PrintValue( node, L"Console file", diff --git a/src/OrcCommand/Command/WolfLauncher/WolfLauncher_Run.cpp b/src/OrcCommand/Command/WolfLauncher/WolfLauncher_Run.cpp index ac301e16..07648b39 100644 --- a/src/OrcCommand/Command/WolfLauncher/WolfLauncher_Run.cpp +++ b/src/OrcCommand/Command/WolfLauncher/WolfLauncher_Run.cpp @@ -610,9 +610,7 @@ HRESULT Orc::Command::Wolf::Main::CreateAndUploadOutline() writer->BeginElement(L"dfir-orc"); writer->BeginElement(L"outline"); { - std::wstring id; - Orc::ToString(m_guid, std::back_inserter(id)); - writer->WriteNamed(L"id", id); + writer->WriteNamed(L"id", ToStringW(SystemDetails::GetOrcRunId())); writer->WriteNamed(L"version", kOrcFileVerStringW); @@ -848,7 +846,7 @@ Orc::Result Main::CreateAndUploadOutcome() auto [outcome, lock] = m_outcome.Get(); - ::UpdateOutcome(outcome, m_guid, m_hMothership); + ::UpdateOutcome(outcome, SystemDetails::GetOrcRunId(), m_hMothership); ::UpdateOutcome(outcome, config.m_Recipients); ::UpdateOutcome(outcome, m_standardOutput); ::UpdateOutcome(outcome, m_logging); diff --git a/src/OrcLib/SystemDetails.cpp b/src/OrcLib/SystemDetails.cpp index 9373e431..48eb7a4c 100644 --- a/src/OrcLib/SystemDetails.cpp +++ b/src/OrcLib/SystemDetails.cpp @@ -57,6 +57,7 @@ struct SystemDetailsBlock std::wstring strFullComputerName; std::wstring strTimeStamp; Traits::TimeUtc timestamp; + GUID orcRunId; std::optional strOrcComputerName; std::optional strOrcFullComputerName; std::optional strProductType; @@ -878,6 +879,16 @@ Result> SystemDetails::GetTimeStamp() return g_pDetailsBlock->timestamp; } +void SystemDetails::SetOrcRunId(const GUID& guid) +{ + g_pDetailsBlock->orcRunId = guid; +} + +const GUID& SystemDetails::GetOrcRunId() +{ + return g_pDetailsBlock->orcRunId; +} + HRESULT SystemDetails::WhoAmI(std::wstring& strMe) { HRESULT hr = E_FAIL; diff --git a/src/OrcLib/SystemDetails.h b/src/OrcLib/SystemDetails.h index ffcb37eb..4fec0bd7 100644 --- a/src/OrcLib/SystemDetails.h +++ b/src/OrcLib/SystemDetails.h @@ -120,6 +120,9 @@ class SystemDetails static Result GetCodePageName(); static Result GetCodePage(); + static void SetOrcRunId(const GUID& guid); + static const GUID& GetOrcRunId(); + static Result GetShutdownTimeFromRegistry(); static Result GetInstallTimeFromRegistry(); static Result GetInstallDateFromRegistry(); From ef9ae2c77a8d47430842633a1b2cf92b77c1a32f Mon Sep 17 00:00:00 2001 From: fabienfl Date: Tue, 30 Apr 2024 14:58:31 +0200 Subject: [PATCH 25/60] OrcLib: OutputSpec: ApplyPattern: add pattern for '{RunId}' --- src/OrcLib/CommandAgent.cpp | 7 ++++++- src/OrcLib/OutputSpec.cpp | 6 +++++- 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/src/OrcLib/CommandAgent.cpp b/src/OrcLib/CommandAgent.cpp index 8ca1dd45..6fdfce1a 100644 --- a/src/OrcLib/CommandAgent.cpp +++ b/src/OrcLib/CommandAgent.cpp @@ -30,6 +30,7 @@ #include "Log/Log.h" #include "Utils/WinApi.h" +#include "Text/Guid.h" #include "CryptoHashStream.h" using namespace std; @@ -250,6 +251,7 @@ HRESULT CommandAgent::ApplyPattern( static const std::wregex r_ComputerName(L"\\{ComputerName\\}"); static const std::wregex r_TimeStamp(L"\\{TimeStamp\\}"); static const std::wregex r_SystemType(L"\\{SystemType\\}"); + static const std::wregex r_OrcRunId(L"\\{RunId\\}"); auto s0 = Pattern; @@ -276,7 +278,10 @@ HRESULT CommandAgent::ApplyPattern( SystemDetails::GetOrcSystemType(strSystemType); auto s7 = std::regex_replace(s6, r_SystemType, strSystemType); - std::swap(s7, output); + wstring strRunID(ToStringW(SystemDetails::GetOrcRunId())); + auto s8 = std::regex_replace(s7, r_OrcRunId, strRunID); + + std::swap(s8, output); return S_OK; } diff --git a/src/OrcLib/OutputSpec.cpp b/src/OrcLib/OutputSpec.cpp index 52b8eb48..74f5a769 100644 --- a/src/OrcLib/OutputSpec.cpp +++ b/src/OrcLib/OutputSpec.cpp @@ -27,6 +27,7 @@ #include "Archive.h" #include "Utils/WinApi.h" #include "Utils/Uri.h" +#include "Text/Guid.h" using namespace std; namespace fs = std::filesystem; @@ -88,6 +89,8 @@ OutputSpec::ApplyPattern(const std::wstring& strPattern, const std::wstring& str wstring strSystemType; SystemDetails::GetOrcSystemType(strSystemType); + wstring strRunId(Orc::ToStringW(SystemDetails::GetOrcRunId())); + strFileName = fmt::vformat( fmt::wstring_view(strPattern), fmt::make_wformat_args( @@ -97,7 +100,8 @@ OutputSpec::ApplyPattern(const std::wstring& strPattern, const std::wstring& str fmt::arg(L"ComputerName", strComputerName), fmt::arg(L"FullComputerName", strFullComputerName), fmt::arg(L"TimeStamp", strTimeStamp), - fmt::arg(L"SystemType", strSystemType))); + fmt::arg(L"SystemType", strSystemType), + fmt::arg(L"RunId", strRunId))); return S_OK; } From b42d6ee39048fd0b87355ef4bc15369acf70664e Mon Sep 17 00:00:00 2001 From: Jean Gautier Date: Fri, 17 Nov 2023 18:04:41 +0100 Subject: [PATCH 26/60] OrcLib: Guard: ViewOfFile: template sometimes require 'this->' --- src/OrcLib/Utils/Guard.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/OrcLib/Utils/Guard.h b/src/OrcLib/Utils/Guard.h index b325f2e2..99ab67e9 100644 --- a/src/OrcLib/Utils/Guard.h +++ b/src/OrcLib/Utils/Guard.h @@ -360,12 +360,12 @@ class ViewOfFile final : public PointerGuard ~ViewOfFile() { - if (m_data == nullptr) + if (this->m_data == nullptr) { return; } - if (::UnmapViewOfFile(m_data) == FALSE) + if (::UnmapViewOfFile(this->m_data) == FALSE) { Log::Warn("Failed UnmapViewOfFile [{}]", LastWin32Error()); } From bc10abc2c8f11764e72bc9aef7146e0e19814575 Mon Sep 17 00:00:00 2001 From: Jean Gautier Date: Sun, 26 Nov 2023 11:54:36 +0100 Subject: [PATCH 27/60] OrcLib: Buffer: initialize constructed stack array --- src/OrcLib/Buffer.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/OrcLib/Buffer.h b/src/OrcLib/Buffer.h index 5b3682a5..0eb453e6 100644 --- a/src/OrcLib/Buffer.h +++ b/src/OrcLib/Buffer.h @@ -227,7 +227,7 @@ class Buffer return *this; }; - // explicitely deleting copy operators + // explicitly deleting copy operators ViewStore(const ViewStore& other) = delete; ViewStore& operator=(const ViewStore& other) = delete; @@ -339,7 +339,7 @@ class Buffer constexpr bool owns() const { return true; } - _T m_Elts[_DeclElts]; + _T m_Elts[_DeclElts] {}; }; struct EmptyStore From b63499a8296f260b7028537fd85cce038df32a74 Mon Sep 17 00:00:00 2001 From: Jean Gautier Date: Thu, 7 Dec 2023 18:02:16 +0100 Subject: [PATCH 28/60] OrcLib: ArchiveCreate: add missing 'const' method qualifier --- src/OrcLib/ArchiveCreate.cpp | 12 ++++++------ src/OrcLib/ArchiveCreate.h | 2 +- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/OrcLib/ArchiveCreate.cpp b/src/OrcLib/ArchiveCreate.cpp index b40c5b3a..0e1d1720 100644 --- a/src/OrcLib/ArchiveCreate.cpp +++ b/src/OrcLib/ArchiveCreate.cpp @@ -47,23 +47,23 @@ ArchiveCreate::ArchiveCreate(bool bComputeHash) ArchiveCreate::~ArchiveCreate(void) {} -std::shared_ptr ArchiveCreate::GetStreamToAdd(const std::shared_ptr& astream) +std::shared_ptr ArchiveCreate::GetStreamToAdd(const std::shared_ptr& stream) const { HRESULT hr = E_FAIL; - if (astream == nullptr) + if (stream == nullptr) return nullptr; - // Move back to the begining of the stream - astream->SetFilePointer(0LL, FILE_BEGIN, nullptr); + // Move back to the beginning of the stream + stream->SetFilePointer(0LL, FILE_BEGIN, nullptr); if (!m_bComputeHash) { - return astream; + return stream; } auto pHashStream = make_shared(); - hr = pHashStream->OpenToRead(CryptoHashStream::Algorithm::MD5 | CryptoHashStream::Algorithm::SHA1, astream); + hr = pHashStream->OpenToRead(CryptoHashStream::Algorithm::MD5 | CryptoHashStream::Algorithm::SHA1, stream); if (FAILED(hr)) { return nullptr; diff --git a/src/OrcLib/ArchiveCreate.h b/src/OrcLib/ArchiveCreate.h index 88a5fa48..d83a34c6 100644 --- a/src/OrcLib/ArchiveCreate.h +++ b/src/OrcLib/ArchiveCreate.h @@ -31,7 +31,7 @@ class ArchiveCreate : public OrcArchive ArchiveFormat m_Format; ArchiveItems m_Queue; - std::shared_ptr GetStreamToAdd(const std::shared_ptr& astream); + std::shared_ptr GetStreamToAdd(const std::shared_ptr& astream) const; ArchiveCreate(bool bComputeHash); From 4b5cc5e8defbe99ef0e848859ccafd11c24e7324 Mon Sep 17 00:00:00 2001 From: Jean Gautier Date: Wed, 3 Apr 2024 10:55:46 +0200 Subject: [PATCH 29/60] OrcLib: BinaryBuffer: add const qualifier to operator== --- src/OrcLib/BinaryBuffer.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/OrcLib/BinaryBuffer.h b/src/OrcLib/BinaryBuffer.h index 1f9b9e7b..6778fcf0 100644 --- a/src/OrcLib/BinaryBuffer.h +++ b/src/OrcLib/BinaryBuffer.h @@ -288,7 +288,7 @@ class CBinaryBuffer return (T*)((BYTE*)m_pData + m_size); }; - bool operator==(const CBinaryBuffer& other) + bool operator==(const CBinaryBuffer& other) const { if (GetCount() != other.GetCount()) return false; From e078485cc456fa61d15666e0b91f62b9f9f47b24 Mon Sep 17 00:00:00 2001 From: Jean Gautier Date: Wed, 3 Apr 2024 10:57:42 +0200 Subject: [PATCH 30/60] OrcLib: BufferStream: remove useless calling convention --- src/OrcLib/BufferStream.h | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/OrcLib/BufferStream.h b/src/OrcLib/BufferStream.h index 342ff15c..65e42706 100644 --- a/src/OrcLib/BufferStream.h +++ b/src/OrcLib/BufferStream.h @@ -78,8 +78,7 @@ class BufferStream : public ByteStream }; template -inline STDMETHODIMP_(HRESULT __stdcall) - BufferStream<_DeclElts>::Read_(PVOID pBuffer, ULONGLONG cbBytes, PULONGLONG pcbBytesRead) +inline STDMETHODIMP BufferStream<_DeclElts>::Read_(PVOID pBuffer, ULONGLONG cbBytes, PULONGLONG pcbBytesRead) { using namespace msl::utilities; @@ -104,7 +103,7 @@ inline STDMETHODIMP_(HRESULT __stdcall) } template -inline STDMETHODIMP_(HRESULT __stdcall) +inline STDMETHODIMP BufferStream<_DeclElts>::Write_(const PVOID pBuffer, ULONGLONG cbBytesToWrite, PULONGLONG pcbBytesWritten) { using namespace msl::utilities; @@ -159,7 +158,7 @@ inline STDMETHODIMP_(HRESULT __stdcall) } template -inline STDMETHODIMP_(HRESULT __stdcall) +inline STDMETHODIMP BufferStream<_DeclElts>::SetFilePointer(LONGLONG DistanceToMove, DWORD dwMoveMethod, PULONG64 pCurrPointer) { HRESULT hr = E_FAIL; From b447997484b292f062af5a44cec5423c66df973b Mon Sep 17 00:00:00 2001 From: Jean Gautier Date: Wed, 3 Apr 2024 10:58:38 +0200 Subject: [PATCH 31/60] OrcLib: SystemDetails: fix missing return statement --- src/OrcLib/SystemDetails.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/OrcLib/SystemDetails.cpp b/src/OrcLib/SystemDetails.cpp index 48eb7a4c..2f013a39 100644 --- a/src/OrcLib/SystemDetails.cpp +++ b/src/OrcLib/SystemDetails.cpp @@ -1287,7 +1287,7 @@ Result> Orc::SystemDetails::GetMo L"Name,FileSystem,Label,DeviceID,DriveType,Capacity,FreeSpace,SerialNumber,BootVolume,SystemVolume," L"LastErrorCode,ErrorDescription FROM Win32_Volume"); if (result.has_error()) - result.error(); + return result.error(); const auto& pEnum = result.value(); From 8bcd3261521fdc529ec419fe7cd9f208daad0b43 Mon Sep 17 00:00:00 2001 From: Jean Gautier Date: Wed, 3 Apr 2024 10:59:42 +0200 Subject: [PATCH 32/60] OrcLib: UncompressNTFSStream: remove dependency on VolumeStreamReader.h --- src/OrcLib/UncompressNTFSStream.cpp | 3 +++ src/OrcLib/UncompressNTFSStream.h | 2 ++ 2 files changed, 5 insertions(+) diff --git a/src/OrcLib/UncompressNTFSStream.cpp b/src/OrcLib/UncompressNTFSStream.cpp index c19d7551..e664b6bb 100644 --- a/src/OrcLib/UncompressNTFSStream.cpp +++ b/src/OrcLib/UncompressNTFSStream.cpp @@ -490,3 +490,6 @@ HRESULT UncompressNTFSStream::SetFilePointer( llCUAlignedPosition = (m_ullPosition / m_dwCompressionUnit) * m_dwCompressionUnit; return NTFSStream::SetFilePointer(llCUAlignedPosition, FILE_BEGIN, &ullChainedPosition); } + +Orc::UncompressNTFSStream::~UncompressNTFSStream() +{} diff --git a/src/OrcLib/UncompressNTFSStream.h b/src/OrcLib/UncompressNTFSStream.h index d45a9a20..457c936b 100644 --- a/src/OrcLib/UncompressNTFSStream.h +++ b/src/OrcLib/UncompressNTFSStream.h @@ -40,6 +40,8 @@ class UncompressNTFSStream : public NTFSStream STDMETHOD(SetFilePointer) (__in LONGLONG DistanceToMove, __in DWORD dwMoveMethod, __out_opt PULONG64 pCurrPointer); + ~UncompressNTFSStream(); + private: HRESULT ReadRaw(CBinaryBuffer& buffer, size_t length); From f86aebe9621c616df21322bfd6c9f294eeb9b93d Mon Sep 17 00:00:00 2001 From: Jean Gautier Date: Wed, 3 Apr 2024 11:06:49 +0200 Subject: [PATCH 33/60] OrcLib: OrcException: remove dependency on Result.h --- src/OrcLib/OrcException.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/OrcLib/OrcException.h b/src/OrcLib/OrcException.h index 5604209e..62d10a45 100644 --- a/src/OrcLib/OrcException.h +++ b/src/OrcLib/OrcException.h @@ -94,7 +94,7 @@ class Exception : public std::exception } explicit Exception(_In_ HRESULT hr) - : m_ec(SystemError(hr)) + : m_ec({hr, std::system_category()}) { } @@ -105,7 +105,7 @@ class Exception : public std::exception Exception(Severity status, _In_ HRESULT hr) : m_severity(status) - , m_ec(SystemError(hr)) + , m_ec({hr, std::system_category()}) { } Exception(Severity status, _In_ std::error_code ec) @@ -126,7 +126,7 @@ class Exception : public std::exception HRESULT SetHRESULT(_In_ HRESULT Status) { - m_ec = SystemError(Status); + m_ec.assign(Status, std::system_category()); return Status; } From 11f6db337a631c21665b5b1af6925848d0495bd5 Mon Sep 17 00:00:00 2001 From: Jean Gautier Date: Wed, 3 Apr 2024 11:08:46 +0200 Subject: [PATCH 34/60] OrcLib: Text: in_addr: use NtError --- src/OrcLib/Text/in_addr.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/OrcLib/Text/in_addr.cpp b/src/OrcLib/Text/in_addr.cpp index 2992eb4b..a53aa628 100644 --- a/src/OrcLib/Text/in_addr.cpp +++ b/src/OrcLib/Text/in_addr.cpp @@ -32,7 +32,7 @@ RtlIpv4AddressToStringExAApi(const in_addr* Address, USHORT Port, PSTR AddressSt auto status = fn(Address, Port, AddressString, AddressStringLength); if (!NT_SUCCESS(status)) { - return std::error_code(HRESULT_FROM_NT(status), std::system_category()); + return Orc::NtError(status); } return Orc::Success(); @@ -58,7 +58,7 @@ RtlIpv4AddressToStringExWApi(const in_addr* Address, USHORT Port, PWSTR AddressS auto status = fn(Address, Port, AddressString, AddressStringLength); if (!NT_SUCCESS(status)) { - return std::error_code(HRESULT_FROM_NT(status), std::system_category()); + return Orc::NtError(status); } return Orc::Success(); @@ -88,7 +88,7 @@ Orc::Result RtlIpv6AddressToStringExAApi( auto status = fn(Address, ScopeId, Port, AddressString, AddressStringLength); if (!NT_SUCCESS(status)) { - return std::error_code(HRESULT_FROM_NT(status), std::system_category()); + return Orc::NtError(status); } return Orc::Success(); @@ -118,7 +118,7 @@ Orc::Result RtlIpv6AddressToStringExWApi( auto status = fn(Address, ScopeId, Port, AddressString, AddressStringLength); if (!NT_SUCCESS(status)) { - return std::error_code(HRESULT_FROM_NT(status), std::system_category()); + return Orc::NtError(status); } return Orc::Success(); From 90f3adbd60edecdc74ac5069c8c73ae2f6966c03 Mon Sep 17 00:00:00 2001 From: Jean Gautier Date: Wed, 3 Apr 2024 11:10:47 +0200 Subject: [PATCH 35/60] OrcLib: Location: fix deprecated std::errc::no_stream_resources --- src/OrcLib/Location.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/OrcLib/Location.cpp b/src/OrcLib/Location.cpp index f8ee0352..7a625c45 100644 --- a/src/OrcLib/Location.cpp +++ b/src/OrcLib/Location.cpp @@ -524,7 +524,7 @@ void Location::EnumerateShadowCopiesWithInternalParser( if (!reader) { Log::Debug("Failed to get reader"); - ec = std::make_error_code(std::errc::no_stream_resources); + ec = std::make_error_code(std::errc::not_enough_memory); return; } From 69b4f37b3d8b8a3ba9da8f416200bc14fa8feb90 Mon Sep 17 00:00:00 2001 From: Jean Gautier Date: Wed, 3 Apr 2024 11:14:06 +0200 Subject: [PATCH 36/60] OrcLib: Filesystem: WofReparsePoint: remove uneedded std::make_error_code --- .../Ntfs/Attribute/ReparsePoint/WofReparsePoint.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/OrcLib/Filesystem/Ntfs/Attribute/ReparsePoint/WofReparsePoint.cpp b/src/OrcLib/Filesystem/Ntfs/Attribute/ReparsePoint/WofReparsePoint.cpp index d7dad672..bb99c440 100644 --- a/src/OrcLib/Filesystem/Ntfs/Attribute/ReparsePoint/WofReparsePoint.cpp +++ b/src/OrcLib/Filesystem/Ntfs/Attribute/ReparsePoint/WofReparsePoint.cpp @@ -18,7 +18,7 @@ Result WofReparsePoint::Parse(BufferView buffer) if (buffer.size() < sizeof(WofReparsePoint::Layout)) { Log::Debug("Failed to parse wof reparse point: invalid size"); - return std::make_error_code(std::errc::message_size); + return std::errc::message_size; } return WofReparsePoint::Parse(*reinterpret_cast(buffer.data())); @@ -29,20 +29,20 @@ Result WofReparsePoint::Parse(const WofReparsePoint::Layout& la if (layout.version != 1) { Log::Debug("Failed to parse wof reparse point: unsupported version (version: {})", layout.version); - return std::make_error_code(std::errc::bad_message); + return std::errc::bad_message; } if (layout.providerVersion != 1) { Log::Debug( "Failed to parse wof reparse point: unsupported provider version (version: {})", layout.providerVersion); - return std::make_error_code(std::errc::bad_message); + return std::errc::bad_message; } if (layout.provider != std::underlying_type_t(WofProviderType::kFile)) { Log::Debug("Failed to parse wof reparse point: unsupported provider (version: {})", layout.provider); - return std::make_error_code(std::errc::bad_message); + return std::errc::bad_message; } std::error_code ec; From 09c0e1ff92bfd90931bb9eb227b906c1d281e164 Mon Sep 17 00:00:00 2001 From: Jean Gautier Date: Sun, 7 Apr 2024 22:55:48 +0200 Subject: [PATCH 37/60] OrcLib: add std::expected support --- src/OrcLib/Authenticode.cpp | 2 +- src/OrcLib/DriverMgmt.h | 2 +- src/OrcLib/OrcLib.h | 1 + src/OrcLib/Text/Format.h | 6 +- src/OrcLib/Text/Iconv.h | 1 + src/OrcLib/Utils/Dump.h | 2 +- src/OrcLib/Utils/Result.h | 182 +++++++++++++++++++++++++++++++----- 7 files changed, 165 insertions(+), 31 deletions(-) diff --git a/src/OrcLib/Authenticode.cpp b/src/OrcLib/Authenticode.cpp index d18ca405..bfcc5d1a 100644 --- a/src/OrcLib/Authenticode.cpp +++ b/src/OrcLib/Authenticode.cpp @@ -153,7 +153,7 @@ Orc::Result CheckCatalogSignature(std::string_view catalog) } } - return Success(); + return Orc::Success(); } bool FindPeHash(std::string_view buffer, const Orc::Authenticode::PE_Hashs& peHashes) diff --git a/src/OrcLib/DriverMgmt.h b/src/OrcLib/DriverMgmt.h index b4b33e15..34906c64 100644 --- a/src/OrcLib/DriverMgmt.h +++ b/src/OrcLib/DriverMgmt.h @@ -166,7 +166,7 @@ class Driver : public std::enable_shared_from_this NULL); FAILED(hr)) return SystemError(hr); - return Success {}; + return {}; } template diff --git a/src/OrcLib/OrcLib.h b/src/OrcLib/OrcLib.h index 50f19d89..9c16d14a 100644 --- a/src/OrcLib/OrcLib.h +++ b/src/OrcLib/OrcLib.h @@ -11,6 +11,7 @@ #include #include +#include #include #include #include diff --git a/src/OrcLib/Text/Format.h b/src/OrcLib/Text/Format.h index add63a3b..363aab6a 100644 --- a/src/OrcLib/Text/Format.h +++ b/src/OrcLib/Text/Format.h @@ -71,20 +71,20 @@ inline void FormatWithEncodingTo(OutputIt out, FmtArg0&& arg0, FmtArgs&&... args if constexpr (std::is_same_v) { - fmt::format_to(out, std::forward(arg0), std::forward(args)...); + fmt::format_to(out, std::forward(arg0), args...); } else if constexpr (std::is_same_v) { fmt::basic_memory_buffer utf8; fmt::vformat_to( - std::back_inserter(utf8), fmt::string_view(arg0), fmt::make_format_args(std::forward(args)...)); + std::back_inserter(utf8), fmt::string_view(arg0), fmt::make_format_args(args...)); details::ToUtf16(utf8, out); } else if constexpr (std::is_same_v) { fmt::basic_memory_buffer utf16; fmt::vformat_to( - std::back_inserter(utf16), fmt::wstring_view(arg0), fmt::make_wformat_args(std::forward(args)...)); + std::back_inserter(utf16), fmt::wstring_view(arg0), fmt::make_wformat_args(args...)); details::ToUtf8(utf16, out); } else diff --git a/src/OrcLib/Text/Iconv.h b/src/OrcLib/Text/Iconv.h index c65340aa..c9cfc8ed 100644 --- a/src/OrcLib/Text/Iconv.h +++ b/src/OrcLib/Text/Iconv.h @@ -8,6 +8,7 @@ #pragma once #include +#include #include #include diff --git a/src/OrcLib/Utils/Dump.h b/src/OrcLib/Utils/Dump.h index 0d0b3a5c..6e969934 100644 --- a/src/OrcLib/Utils/Dump.h +++ b/src/OrcLib/Utils/Dump.h @@ -50,7 +50,7 @@ Result Dump(const T& container, const std::filesystem::path& output) return std::make_error_code(std::errc::message_size); } - return Orc::Success<>(); + return {}; } } // namespace Orc diff --git a/src/OrcLib/Utils/Result.h b/src/OrcLib/Utils/Result.h index d7ed2012..26f0b591 100644 --- a/src/OrcLib/Utils/Result.h +++ b/src/OrcLib/Utils/Result.h @@ -8,10 +8,133 @@ #pragma once #include +#include +#include +#include -#include +#ifdef __cpp_lib_expected +# include + +namespace Orc { + +template +concept not_void = !std::is_same_v; + +template +struct Result : std::expected +{ + constexpr Result(Result&& value) noexcept = default; + constexpr Result(const Result& value) noexcept = delete; + + constexpr Result& operator=(Result&& value) noexcept = default; + constexpr Result& operator=(const Result& value) noexcept = default; + + constexpr Result& operator=(const std::errc& ec) + { + return *this = std::unexpected(std::make_error_code(ec)); + } + + constexpr Result& operator=(const std::error_code& ec) + { + return *this = std::unexpected(ec); + } + + template + constexpr Result(U&& value) noexcept + requires(!std::is_same_v && std::is_convertible_v) + : std::expected(std::forward(value)) {}; + + constexpr Result(std::errc ec) + : std::expected(std::unexpected(std::make_error_code(ec))) {}; + + constexpr Result(std::error_code ec) + : std::expected(std::unexpected(ec)) {}; + + constexpr Result(std::unexpected unexpected) + : std::expected(std::move(unexpected)) {}; + + template + constexpr Result(Args&&... args) noexcept + requires std::constructible_from + : std::expected(std::in_place, args...) + { + } + + constexpr inline bool has_error() const { return !this->has_value(); } +}; + + +template <> +struct Result : std::expected +{ + + constexpr Result(std::errc ec) + : std::expected(std::unexpected(std::make_error_code(ec))) {}; + + Result(std::error_code ec) noexcept + : std::expected(std::unexpected(ec)) {}; + + Result(std::unexpected unexpected) + : std::expected(std::move(unexpected)) {}; + + template + constexpr Result(Args&&... args) + : std::expected() + { + } + + constexpr inline bool has_error() const { return !this->has_value(); } +}; + +template +inline Result Success(auto... args) + requires not_void && std::constructible_from +{ + return {std::in_place, args...}; +} + +template <> +inline Result Success() +{ + return {std::in_place}; +} + +using Fail = std::unexpected; + + +inline std::error_code SystemError(HRESULT hr) +{ + return {hr, std::system_category()}; +} + +inline std::error_code Win32Error(DWORD win32Error) +{ + return {HRESULT_FROM_WIN32(win32Error), std::system_category()}; +} + +inline std::error_code NtError(NTSTATUS ntStatus) +{ + return std::error_code {HRESULT_FROM_NT(ntStatus), std::system_category()}; +} + +// Return std::error_code from GetLastError() value +inline std::error_code LastWin32Error() +{ + return std::error_code {HRESULT_FROM_WIN32(::GetLastError()), std::system_category()}; +} + +} // namespace Orc + +# define ORC_TRY(value, expr) \ + auto&& _result = expr; \ + if (!_result.has_value()) \ + return std::unexpected(_result.error()); \ + auto value = *_result; + +#else + +# include -#include namespace Orc { @@ -64,8 +187,38 @@ struct Result : boost::outcome_v2::std_result } }; -template -using Success = boost::outcome_v2::success_type; +template +inline Result Success(Args&&... args) +{ + return {boost::outcome_v2::in_place_type, args...}; +} + +inline std::error_code SystemError(HRESULT hr) +{ + return {hr, std::system_category()}; +} + +inline std::error_code Win32Error(DWORD win32Error) +{ + return {HRESULT_FROM_WIN32(win32Error), std::system_category()}; +} + +inline std::error_code NtError(NTSTATUS ntStatus) +{ + return {HRESULT_FROM_NT(ntStatus), std::system_category()}; +} + +// Return std::error_code from GetLastError() value +inline std::error_code LastWin32Error() +{ + return {HRESULT_FROM_WIN32(::GetLastError()), std::system_category()}; +} + +} // namespace Orc + +#endif + +namespace Orc { template T& operator*(Result& result) @@ -123,27 +276,6 @@ T ValueOr(Orc::Result&& result, T&& fallback_value) return std::move(fallback_value); } -inline std::error_code SystemError(HRESULT hr) -{ - return {hr, std::system_category()}; -} - -inline std::error_code Win32Error(DWORD win32Error) -{ - return {HRESULT_FROM_WIN32(win32Error), std::system_category()}; -} - -inline std::error_code NtError(NTSTATUS ntStatus) -{ - return {HRESULT_FROM_NT(ntStatus), std::system_category()}; -} - -// Return std::error_code from GetLastError() value -inline std::error_code LastWin32Error() -{ - return {HRESULT_FROM_WIN32(::GetLastError()), std::system_category()}; -} - inline HRESULT ToHRESULT(const std::error_code& ec) { if (ec.category() != std::system_category()) From eb4e6c265cae56d45deb308dd9d721f386cda918 Mon Sep 17 00:00:00 2001 From: Jean Gautier Date: Wed, 10 Apr 2024 19:41:55 +0200 Subject: [PATCH 38/60] OrcLib: Buffer: add noexcept keyword to operator= --- src/OrcLib/Buffer.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/OrcLib/Buffer.h b/src/OrcLib/Buffer.h index 0eb453e6..b6bcf3df 100644 --- a/src/OrcLib/Buffer.h +++ b/src/OrcLib/Buffer.h @@ -761,7 +761,7 @@ class Buffer assign(Ptr); return *this; } - Buffer<_T, _DeclElts>& operator=(_In_ Buffer<_T, _DeclElts>&& Ptr) + Buffer<_T, _DeclElts>& operator=(_In_ Buffer<_T, _DeclElts>&& Ptr) noexcept { std::swap(m_store, Ptr.m_store); std::swap(m_EltsUsed, Ptr.m_EltsUsed); From bd12b2e8eb85dc2e9ea88dfe214b33e1ad2a65e6 Mon Sep 17 00:00:00 2001 From: Jean Gautier Date: Tue, 23 Apr 2024 17:25:36 +0200 Subject: [PATCH 39/60] OrcLib: OrcException: fix fmt header inclusion --- src/OrcLib/OrcException.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/OrcLib/OrcException.cpp b/src/OrcLib/OrcException.cpp index 74e9b781..9050d4eb 100644 --- a/src/OrcLib/OrcException.cpp +++ b/src/OrcLib/OrcException.cpp @@ -12,7 +12,7 @@ #include "WideAnsi.h" -#include "fmt/format.h" +#include #include "Log/Log.h" From 1fb8ba94d9eba7bd09d79c4440fdd2ba606feaab Mon Sep 17 00:00:00 2001 From: Jean Gautier Date: Wed, 3 Apr 2024 10:57:12 +0200 Subject: [PATCH 40/60] cmake: keep CMAKE_CXX_STANDARD or set default to cpp17 --- cmake/Orc.cmake | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/cmake/Orc.cmake b/cmake/Orc.cmake index ded3fb74..4fed8b73 100644 --- a/cmake/Orc.cmake +++ b/cmake/Orc.cmake @@ -9,8 +9,10 @@ macro(orc_add_compile_options) -set(CMAKE_CXX_STANDARD 17) -set(CMAKE_CXX_STANDARD_REQUIRED ON) +if (NOT DEFINED CMAKE_CXX_STANDARD) + set(CMAKE_CXX_STANDARD 17) + set(CMAKE_CXX_STANDARD_REQUIRED ON) +endif() add_compile_definitions( UNICODE From 263ef1a602a1bd79f908381edd81cf7c50867505 Mon Sep 17 00:00:00 2001 From: Jean Gautier Date: Wed, 20 Sep 2023 15:59:42 +0200 Subject: [PATCH 41/60] OrcLib: Buffer: replace stdext::checked_array_iterator with gsl::span --- src/OrcLib/Buffer.h | 206 +++++++++++++++++++++++++++++++++++--------- 1 file changed, 166 insertions(+), 40 deletions(-) diff --git a/src/OrcLib/Buffer.h b/src/OrcLib/Buffer.h index b6bcf3df..a863f60b 100644 --- a/src/OrcLib/Buffer.h +++ b/src/OrcLib/Buffer.h @@ -16,6 +16,8 @@ #include "Log/Log.h" #include +#include + #pragma managed(push, off) namespace Orc { @@ -93,6 +95,106 @@ class BufferSpan ZeroMemory(get(position), std::min(size_ - position, elements) * sizeof(_T)); } + bool operator==(const BufferSpan& rhs) const + { + if (rhs.size() != size()) + return false; + return get() == rhs.get(); + } + + using value_type = typename _T; + using reference = typename value_type&; + using const_reference = const typename value_type&; + using pointer = typename value_type*; + using const_pointer = const typename value_type*; + + class const_iterator + { + template + friend class BufferSpan; + public: + const_iterator(const_iterator&& other) noexcept = default; + const_iterator(const const_iterator& other) noexcept = default; + + ~const_iterator() {}; + + bool operator==(const const_iterator& other) const + { + return m_span == other.m_span && m_current == other.m_current; + } + bool operator!=(const const_iterator& other) const { return !operator==(other); } + + const_iterator& operator++() + { + assert(m_current != nullptr && "Iterator is NULL"); + if (m_current >= m_span.get() + m_span.size()) + throw Orc::Exception(Severity::Fatal, E_BOUNDS); + + m_current++; + return *this; + } + const_reference operator*() const { return *m_current; } + const_pointer operator->() const { return m_current; } + + private: + + const_iterator(const BufferSpan& _span, const _T* pos) + : m_span(_span) + { + assert(pos != nullptr && "Iterator is NULL"); + assert(pos >= m_span.get() && pos <= m_span.get() + m_span.size()); + m_current = const_cast<_T*>(pos); + } + const BufferSpan m_span; + mutable _T* m_current; + }; + + class iterator + { + template + friend class BufferSpan; + public: + iterator(iterator&& other) noexcept = default; + iterator(const iterator& other) noexcept = default; + + ~iterator() {}; + + bool operator==(const iterator& other) const + { + return m_span == other.m_span && m_current == other.m_current; + } + bool operator!=(const iterator& other) const {return !operator==(other);} + + iterator& operator++() + { + assert(m_current != nullptr && "Iterator is NULL"); + if (m_current >= m_span.get() + m_span.size()) + throw Orc::Exception(Severity::Fatal, E_BOUNDS); + + m_current++; + return *this; + } + reference operator*() const { return *m_current; } + pointer operator->() const { return m_current; } + + private: + iterator(const BufferSpan& _span, const _T* pos) + : m_span(_span) + { + assert(pos != nullptr && "Iterator is NULL"); + assert(pos >= m_span.get() && pos <= m_span.get() + m_span.size()); + m_current = const_cast<_T*>(pos); + } + const BufferSpan m_span; + mutable _T* m_current; + }; + +public: + iterator begin() const { return iterator(*this, get()); } + const_iterator cbegin() const { return const_iterator(*this, get()); } + iterator end() const { return iterator(*this, get() + size()); } + const_iterator cend() const { return const_iterator(*this, get() + size()); } + private: _T* m_Ptr; ULONG m_Elts; @@ -146,7 +248,8 @@ class Buffer { reserve(Elts); } - std::copy(Ptr, Ptr + Elts, stdext::checked_array_iterator(m_Ptr, m_EltsAlloc)); + gsl::span span(m_Ptr, m_EltsAlloc); + std::copy(Ptr, Ptr + Elts, std::begin(span)); return; } @@ -175,7 +278,8 @@ class Buffer m_Ptr = new _T[Elts]; m_EltsAlloc = Elts; - std::copy(OldPtr, OldPtr + OldEltsAlloc, stdext::checked_array_iterator(m_Ptr, m_EltsAlloc)); + gsl::span span(m_Ptr, m_EltsAlloc); + std::copy(OldPtr, OldPtr + OldEltsAlloc, std::begin(span)); delete[] OldPtr; } @@ -237,8 +341,8 @@ class Buffer { if (Elts > m_EltsInView) throw Orc::Exception(Severity::Fatal, E_OUTOFMEMORY); - - std::copy(Ptr, Ptr + Elts, stdext::checked_array_iterator(m_Ptr, m_EltsInView)); + gsl::span span(m_Ptr, m_EltsInView); + std::copy(Ptr, Ptr + Elts, std::begin(span)); return; } @@ -266,7 +370,8 @@ class Buffer _T* relinquish() { auto ptr = new _T[m_EltsInView]; - std::copy(m_Ptr, m_Ptr + m_EltsInView, stdext::checked_array_iterator(ptr, m_EltsInView)); + gsl::span span(ptr, m_EltsInView); + std::copy(m_Ptr, m_Ptr + m_EltsInView, std::begin(span)); m_Ptr = nullptr; return ptr; } @@ -279,17 +384,10 @@ class Buffer { friend void swap(InnerStore& left, InnerStore& right) noexcept { - _T temp[_DeclElts]; - std::copy( - std::begin(left.m_Elts), - std::end(left.m_Elts), - stdext::checked_array_iterator(std::begin(temp), _DeclElts)); - std::copy( - std::begin(right.m_Elts), - std::end(right.m_Elts), - stdext::checked_array_iterator(std::begin(left.m_Elts), _DeclElts)); - std::copy( - std::begin(temp), std::end(temp), stdext::checked_array_iterator(std::begin(right.m_Elts), _DeclElts)); + std::array<_T, _DeclElts> temp; + std::copy(std::begin(left.m_Elts), std::end(left.m_Elts), std::begin(temp)); + std::copy(std::begin(right.m_Elts), std::end(right.m_Elts), std::begin(temp)); + std::copy(std::begin(temp), std::end(temp), std::begin(temp)); } constexpr InnerStore() = default; @@ -302,7 +400,8 @@ class Buffer template InnerStore(Iterator begin, Iterator end) { - std::copy(begin, end, stdext::checked_array_iterator(m_Elts, _DeclElts)); + gsl::span span(m_Elts, _DeclElts); + std::copy(begin, end, std::begin(span)); } constexpr ULONG capacity() const { return _DeclElts; } @@ -319,7 +418,8 @@ class Buffer throw Orc::Exception( Severity::Fatal, L"Cannot assign %d elements to a {} inner store"sv, Elts, _DeclElts); } - std::copy(Ptr, Ptr + Elts, stdext::checked_array_iterator(m_Elts, _DeclElts)); + gsl::span span(m_Elts, _DeclElts); + std::copy(Ptr, Ptr + Elts, std::begin(span)); return; } @@ -333,7 +433,8 @@ class Buffer _T* relinquish() { auto ptr = new _T[_DeclElts]; - std::copy(m_Elts, m_Elts + _DeclElts, stdext::checked_array_iterator(ptr, _DeclElts)); + gsl::span span(ptr, _DeclElts); + std::copy(m_Elts, m_Elts + _DeclElts, std::begin(span)); return ptr; } @@ -386,9 +487,8 @@ class Buffer Buffer(const std::initializer_list<_T>& list) { - resize((ULONG)list.size()); - std::copy(std::begin(list), std::end(list), stdext::checked_array_iterator(get(), capacity())); - m_EltsUsed = (ULONG)list.size(); + reserve((ULONG)list.size()); + std::copy(std::begin(list), std::end(list), std::back_inserter(*this)); } Buffer(const BufferSpan<_T> span) @@ -523,7 +623,8 @@ class Buffer } } - std::copy(&Src, &Src + 1, stdext::checked_array_iterator(get() + size_, capacity_ - size_)); + gsl::span span(get() + size_, capacity_ - size_); + std::copy(&Src, &Src + 1, std::begin(span)); m_EltsUsed = new_size; } @@ -573,8 +674,8 @@ class Buffer capacity_ = new_capacity; } } - - std::copy(Src, Src + Elts, stdext::checked_array_iterator(get() + size_, capacity_ - size_)); + gsl::span span(get() + size_, capacity_ - size_); + std::copy(Src, Src + Elts, std::begin(span)); m_EltsUsed = new_size; } void append(_In_ const Buffer& Other) { append(Other.get_raw(), Other.size()); } @@ -644,7 +745,9 @@ class Buffer auto new_store = HeapStore(Elts); if (const auto current = get_raw()) { - std::copy(current, current + size(), stdext::checked_array_iterator(new_store.get(), Elts)); + gsl::span new_store_span(new_store.get(), new_store.capacity()); + + std::copy(current, current + size(), std::begin(new_store_span)); } m_store = std::move(new_store); @@ -727,16 +830,14 @@ class Buffer _T* get_raw(ULONG index = 0) const { - return std::visit( - [index](auto&& arg) -> auto{ return arg.get(index); }, m_store); + return std::visit([index](auto&& arg) -> auto { return arg.get(index); }, m_store); } explicit operator _T*(void) const { return get(); } bool owns(void) const { - return std::visit( - [](auto&& arg) -> auto{ return arg.owns(); }, m_store); + return std::visit([](auto&& arg) -> auto { return arg.owns(); }, m_store); } template @@ -948,9 +1049,14 @@ class Buffer class const_iterator { public: - const_iterator(const _T* ptr) { m_current = const_cast<_T*>(ptr); } - const_iterator(const_iterator&& other) noexcept { std::swap(m_current, other.m_current); }; - const_iterator(const const_iterator& other) noexcept { m_current = other.m_current; }; + const_iterator(const _T* ptr, const ULONG size) + : m_current(const_cast<_T*>(ptr)) + , m_end(ptr + size) + { + } + + const_iterator(const_iterator&& other) noexcept = default; + const_iterator(const const_iterator& other) noexcept = default; ~const_iterator() {}; @@ -959,6 +1065,10 @@ class Buffer const_iterator& operator++() { + assert(m_current != nullptr && "Iterator is NULL"); + if (m_current >= m_end) + throw Orc::Exception(Severity::Fatal, E_BOUNDS); + m_current++; return *this; } @@ -967,14 +1077,19 @@ class Buffer private: mutable _T* m_current; + const _T* m_end; }; class iterator { public: - iterator(const _T* ptr) { m_current = const_cast<_T*>(ptr); } - iterator(iterator&& other) noexcept { std::swap(m_current, other.m_current); }; - iterator(const iterator& other) noexcept { m_current = other.m_current; }; + iterator(const _T* ptr, const ULONG size) + : m_current(const_cast<_T*>(ptr)) + , m_end(ptr + size) + { + } + iterator(iterator&& other) noexcept = default; + iterator(const iterator& other) noexcept = default; ~iterator() {}; @@ -983,6 +1098,10 @@ class Buffer iterator& operator++() { + assert(m_current != nullptr && "Iterator is NULL"); + if (m_current >= m_end) + throw Orc::Exception(Severity::Fatal, E_BOUNDS); + m_current++; return *this; } @@ -991,13 +1110,20 @@ class Buffer private: mutable _T* m_current; + const _T* m_end; }; public: - iterator begin() const { return iterator(get_raw()); } - const_iterator cbegin() const { return const_iterator(get_raw()); } - iterator end() const { return iterator(get_raw() + size()); } - const_iterator cend() const { return const_iterator(get_raw() + size()); } + iterator begin() const { return empty() ? iterator(nullptr, 0) : iterator(get(), size()); } + const_iterator cbegin() const { return empty() ? const_iterator(nullptr, 0) : const_iterator(get(), size()); } + iterator end() const + { + return empty() ? iterator(nullptr, 0) : iterator(get() + size(), 0); + } + const_iterator cend() const + { + return empty() ? iterator(nullptr, 0) : const_iterator(get() + size(), 0); + } private: Store m_store; From 716ac45fdeeba8b6dc6b59ea7a6e6cd85bad0c12 Mon Sep 17 00:00:00 2001 From: fabienfl Date: Thu, 2 May 2024 16:27:36 +0200 Subject: [PATCH 42/60] OrcLib: add HypervisorType --- src/OrcLib/CMakeLists.txt | 2 ++ src/OrcLib/HypervisorType.cpp | 54 +++++++++++++++++++++++++++++++++++ src/OrcLib/HypervisorType.h | 24 ++++++++++++++++ 3 files changed, 80 insertions(+) create mode 100644 src/OrcLib/HypervisorType.cpp create mode 100644 src/OrcLib/HypervisorType.h diff --git a/src/OrcLib/CMakeLists.txt b/src/OrcLib/CMakeLists.txt index c8c321ff..f5ab79a6 100644 --- a/src/OrcLib/CMakeLists.txt +++ b/src/OrcLib/CMakeLists.txt @@ -919,6 +919,8 @@ set(SRC_UTILITIES_SYSTEM "CryptoUtilities.h" "DriverMgmt.cpp" "DriverMgmt.h" + "HypervisorType.h" + "HypervisorType.cpp" "JobObject.cpp" "JobObject.h" "Privilege.cpp" diff --git a/src/OrcLib/HypervisorType.cpp b/src/OrcLib/HypervisorType.cpp new file mode 100644 index 00000000..092fa402 --- /dev/null +++ b/src/OrcLib/HypervisorType.cpp @@ -0,0 +1,54 @@ +#include "HypervisorType.h" + +using namespace Orc; +using namespace std::literals::string_view_literals; + +namespace Orc { + +constexpr auto enum_count = static_cast>(HypervisorType::EnumCount); +constexpr std::array, enum_count + 1> kHypervisorTypeEntries = { + std::make_tuple(HypervisorType::Undefined, ""sv), + std::make_tuple(HypervisorType::None, "none"sv), + std::make_tuple(HypervisorType::HyperV, "hyper-v"sv), + std::make_tuple(HypervisorType::VMware, "vwware"sv), + std::make_tuple(HypervisorType::VirtualBox, "virtualbox"sv), + std::make_tuple(HypervisorType::QEMU, "qemu"sv), + std::make_tuple(HypervisorType::Xen, "xen"sv), + std::make_tuple(HypervisorType::EnumCount, ""sv)}; + +Result ToHypervisorType(std::string_view magic) +{ + using underlying_type = std::underlying_type_t; + + for (auto i = 1; i < kHypervisorTypeEntries.size() - 1; i++) + { + if (magic == std::get<1>(kHypervisorTypeEntries[i])) + { + return static_cast(std::get<0>(kHypervisorTypeEntries[i])); + } + } + + return std::make_error_code(std::errc::invalid_argument); +} + +std::string_view ToStringView(HypervisorType type) +{ + using underlying_type = std::underlying_type_t; + constexpr auto enum_count = static_cast(HypervisorType::EnumCount); + + auto id = static_cast(type); + if (id >= enum_count) + { + id = static_cast(HypervisorType::EnumCount); + } + + return std::get<1>(kHypervisorTypeEntries[id]); +} + +std::wstring ToStringW(HypervisorType type) +{ + auto view = ToStringView(type); + return {std::cbegin(view), std::cend(view)}; +} + +} // namespace Orc diff --git a/src/OrcLib/HypervisorType.h b/src/OrcLib/HypervisorType.h new file mode 100644 index 00000000..7fbe74b9 --- /dev/null +++ b/src/OrcLib/HypervisorType.h @@ -0,0 +1,24 @@ +#pragma once + +#include "Utils/Result.h" + +namespace Orc { + +enum class HypervisorType +{ + Undefined = 0, + None, + HyperV, + VMware, + VirtualBox, + QEMU, + Xen, + EnumCount +}; + +std::string_view ToStringView(HypervisorType type); +std::wstring ToStringW(HypervisorType type); + +Result ToHypervisorType(std::string_view record_type); + +} // namespace Orc From 2b329756bf3618a333f4547c297ad2e9c1b542b1 Mon Sep 17 00:00:00 2001 From: fabienfl Date: Thu, 2 May 2024 16:29:56 +0200 Subject: [PATCH 43/60] OrcLib: SystemDetails: add GetHypervisor --- src/OrcLib/SystemDetails.cpp | 110 +++++++++++++++++++++++++++++++++++ src/OrcLib/SystemDetails.h | 3 + 2 files changed, 113 insertions(+) diff --git a/src/OrcLib/SystemDetails.cpp b/src/OrcLib/SystemDetails.cpp index 2f013a39..1c8a5eb1 100644 --- a/src/OrcLib/SystemDetails.cpp +++ b/src/OrcLib/SystemDetails.cpp @@ -44,6 +44,86 @@ inline void CopyUntil(_InIt _First, _InIt _Last, _OutIt _Dest, _Pr _Pred) } } +bool IsRunningInHyperV() +{ + Guard::RegistryHandle hKey; + return RegOpenKeyExA( + HKEY_LOCAL_MACHINE, + "SOFTWARE\\Microsoft\\Virtual Machine\\Guest\\Parameters", + 0, + KEY_READ, + &hKey.value()) + == ERROR_SUCCESS; +} + +bool IsRunningInVMware() +{ + Guard::ServiceHandle hSCManager = OpenSCManager(NULL, NULL, SC_MANAGER_CONNECT); + if (!hSCManager) + { + return false; + } + + Guard::ServiceHandle hService = OpenService(hSCManager.value(), L"vmci", SERVICE_QUERY_STATUS); + if (!hService) + { + return false; + } + + return true; +} + +bool IsRunningInVirtualBox() +{ + Guard::ServiceHandle hSCManager = OpenSCManager(NULL, NULL, SC_MANAGER_CONNECT); + if (!hSCManager) + { + return false; + } + + Guard::ServiceHandle hService = OpenService(hSCManager.value(), L"VBoxGuest", SERVICE_QUERY_STATUS); + if (!hService) + { + return false; + } + + return true; +} + +bool IsRunningInQEMU() +{ + Guard::ServiceHandle hSCManager = OpenSCManager(NULL, NULL, SC_MANAGER_CONNECT); + if (!hSCManager) + { + return false; + } + + Guard::ServiceHandle hService = OpenService(hSCManager.value(), L"QEMU", SERVICE_QUERY_STATUS); + if (!hService) + { + return false; + } + + return true; +} + +bool IsRunningInXen() +{ + Guard::ServiceHandle hSCManager = OpenSCManager(NULL, NULL, SC_MANAGER_CONNECT); + if (!hSCManager) + { + return false; + } + + Guard::ServiceHandle hService = OpenService(hSCManager.value(), L"xenevtchn", SERVICE_QUERY_STATUS); + if (!hService) + { + return false; + } + + return true; +} + } // namespace namespace Orc { @@ -2075,3 +2155,33 @@ HRESULT SystemDetails::GetProcessBinary(std::wstring& strFullPath) strFullPath.assign(szPath); return S_OK; } + +Result Orc::SystemDetails::GetHypervisor() +{ + if (::IsRunningInHyperV()) + { + return HypervisorType::HyperV; + } + + if (::IsRunningInVMware()) + { + return HypervisorType::VMware; + } + + if (::IsRunningInVirtualBox()) + { + return HypervisorType::VirtualBox; + } + + if (::IsRunningInQEMU()) + { + return HypervisorType::QEMU; + } + + if (::IsRunningInXen()) + { + return HypervisorType::Xen; + } + + return HypervisorType::None; +} diff --git a/src/OrcLib/SystemDetails.h b/src/OrcLib/SystemDetails.h index 4fec0bd7..19c9f2bd 100644 --- a/src/OrcLib/SystemDetails.h +++ b/src/OrcLib/SystemDetails.h @@ -12,6 +12,7 @@ #include "Utils/Result.h" #include "Utils/TypeTraits.h" #include "OutputWriter.h" +#include "HypervisorType.h" #include #include @@ -131,6 +132,8 @@ class SystemDetails static HRESULT GetProcessBinary(std::wstring& strFullPath); + static Result GetHypervisor(); + enum DriveType { Drive_Unknown, From f6e8f657eed1c24f70fa81cbf9ba5ddf2bbeb9a1 Mon Sep 17 00:00:00 2001 From: fabienfl Date: Thu, 2 May 2024 16:33:31 +0200 Subject: [PATCH 44/60] OrcCommand: WolfLauncher: Outline: add hypervisor --- src/OrcLib/SystemIdentity.cpp | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/OrcLib/SystemIdentity.cpp b/src/OrcLib/SystemIdentity.cpp index 792d4443..9c00de6b 100644 --- a/src/OrcLib/SystemIdentity.cpp +++ b/src/OrcLib/SystemIdentity.cpp @@ -194,6 +194,14 @@ HRESULT Orc::SystemIdentity::System(const std::shared_ptrWriteNamed(L"hypervisor", ToStringW(*hv)); + } + } + { WORD wArch = 0; SystemDetails::GetArchitecture(wArch); From 3e64ead10473d9d467b5ec01ebec620a0d758e5b Mon Sep 17 00:00:00 2001 From: fabienfl Date: Thu, 2 May 2024 17:49:41 +0200 Subject: [PATCH 45/60] OrcLib: Text: fmt: std_optional: enhance compatibility with std::decay_t --- src/OrcLib/Text/Fmt/std_optional.h | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/OrcLib/Text/Fmt/std_optional.h b/src/OrcLib/Text/Fmt/std_optional.h index 15b73f7a..7dd9cc5c 100644 --- a/src/OrcLib/Text/Fmt/std_optional.h +++ b/src/OrcLib/Text/Fmt/std_optional.h @@ -13,10 +13,10 @@ #include template -struct fmt::formatter> : public fmt::formatter +struct fmt::formatter> : public fmt::formatter> { template - auto format(const std::optional& optional, FormatContext& ctx) -> decltype(ctx.out()) + auto format(const std::optional& optional, FormatContext& ctx) const -> decltype(ctx.out()) { if (!optional.has_value()) { @@ -24,15 +24,15 @@ struct fmt::formatter> : public fmt::formatter return na.format("N/A", ctx); } - return formatter::format(optional.value(), ctx); + return formatter>::format(optional.value(), ctx); } }; template -struct fmt::formatter, wchar_t> : public fmt::formatter +struct fmt::formatter, wchar_t> : public fmt::formatter, wchar_t> { template - auto format(const std::optional& optional, FormatContext& ctx) -> decltype(ctx.out()) + auto format(const std::optional& optional, FormatContext& ctx) const -> decltype(ctx.out()) { if (!optional.has_value()) { @@ -40,6 +40,6 @@ struct fmt::formatter, wchar_t> : public fmt::formatter::format(optional.value(), ctx); + return formatter, wchar_t>::format(optional.value(), ctx); } }; From 543e2b1a0d54f9c535c0930ff2aef4f92d493c3d Mon Sep 17 00:00:00 2001 From: fabienfl Date: Thu, 2 May 2024 18:28:56 +0200 Subject: [PATCH 46/60] OrcLib: Text: fmt: GUID: add const qualifier to method format --- src/OrcLib/Text/Fmt/GUID.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/OrcLib/Text/Fmt/GUID.h b/src/OrcLib/Text/Fmt/GUID.h index e40a9b12..6ba91f4c 100644 --- a/src/OrcLib/Text/Fmt/GUID.h +++ b/src/OrcLib/Text/Fmt/GUID.h @@ -20,7 +20,7 @@ template <> struct fmt::formatter : public fmt::formatter { template - auto format(const GUID& guid, FormatContext& ctx) + auto format(const GUID& guid, FormatContext& ctx) const { fmt::basic_memory_buffer s; Orc::ToString(guid, std::back_inserter(s)); @@ -32,7 +32,7 @@ template <> struct fmt::formatter : public fmt::formatter { template - auto format(const GUID& guid, FormatContext& ctx) + auto format(const GUID& guid, FormatContext& ctx) const { fmt::basic_memory_buffer s; Orc::ToString(guid, std::back_inserter(s)); From d8808b791cb45ddf7e92e425b4b1163c7e21e2b7 Mon Sep 17 00:00:00 2001 From: fabienfl Date: Fri, 3 May 2024 11:40:03 +0200 Subject: [PATCH 47/60] OrcLib: Text: StdoutContainerAdapter: fix missing static_cast --- src/OrcLib/Text/StdoutContainerAdapter.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/OrcLib/Text/StdoutContainerAdapter.h b/src/OrcLib/Text/StdoutContainerAdapter.h index 3b8c6294..83d2105b 100644 --- a/src/OrcLib/Text/StdoutContainerAdapter.h +++ b/src/OrcLib/Text/StdoutContainerAdapter.h @@ -32,7 +32,7 @@ struct StdoutContainerAdapter { DWORD written = 0; auto buffer = ToUtf8(m_buffer); - WriteFile(m_hStdout, (void*)buffer.data(), buffer.size(), &written, NULL); + WriteFile(m_hStdout, (void*)buffer.data(), static_cast(buffer.size()), &written, NULL); } FlushFileBuffers(m_hStdout); @@ -48,7 +48,7 @@ struct StdoutContainerAdapter DWORD written = 0; auto buffer = ToUtf8(m_buffer); - WriteFile(m_hStdout, (void*)buffer.data(), buffer.size(), &written, NULL); + WriteFile(m_hStdout, (void*)buffer.data(), static_cast(buffer.size()), &written, NULL); m_buffer.clear(); } else if (c) From 824c26674662f5e98641467ae8bd3609c775693b Mon Sep 17 00:00:00 2001 From: fabienfl Date: Fri, 3 May 2024 11:52:58 +0200 Subject: [PATCH 48/60] OrcLib: Text: Fmt: Result: fix missing header --- src/OrcLib/Text/Fmt/Result.h | 1 + 1 file changed, 1 insertion(+) diff --git a/src/OrcLib/Text/Fmt/Result.h b/src/OrcLib/Text/Fmt/Result.h index f713301b..d2e17dce 100644 --- a/src/OrcLib/Text/Fmt/Result.h +++ b/src/OrcLib/Text/Fmt/Result.h @@ -10,6 +10,7 @@ #include #include +#include "std_error_code.h" #include "Utils/Result.h" template From d1574d57c99e0ca5852e91c479a1f6a28337ea68 Mon Sep 17 00:00:00 2001 From: fabienfl Date: Fri, 3 May 2024 11:54:40 +0200 Subject: [PATCH 49/60] Revert "OrcLib: Text: fmt: std_optional: enhance compatibility with std::decay_t" This reverts commit 6179e0600b581e139f6354dfa86f017a957dad96. --- src/OrcLib/Text/Fmt/std_optional.h | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/OrcLib/Text/Fmt/std_optional.h b/src/OrcLib/Text/Fmt/std_optional.h index 7dd9cc5c..15b73f7a 100644 --- a/src/OrcLib/Text/Fmt/std_optional.h +++ b/src/OrcLib/Text/Fmt/std_optional.h @@ -13,10 +13,10 @@ #include template -struct fmt::formatter> : public fmt::formatter> +struct fmt::formatter> : public fmt::formatter { template - auto format(const std::optional& optional, FormatContext& ctx) const -> decltype(ctx.out()) + auto format(const std::optional& optional, FormatContext& ctx) -> decltype(ctx.out()) { if (!optional.has_value()) { @@ -24,15 +24,15 @@ struct fmt::formatter> : public fmt::formatter> return na.format("N/A", ctx); } - return formatter>::format(optional.value(), ctx); + return formatter::format(optional.value(), ctx); } }; template -struct fmt::formatter, wchar_t> : public fmt::formatter, wchar_t> +struct fmt::formatter, wchar_t> : public fmt::formatter { template - auto format(const std::optional& optional, FormatContext& ctx) const -> decltype(ctx.out()) + auto format(const std::optional& optional, FormatContext& ctx) -> decltype(ctx.out()) { if (!optional.has_value()) { @@ -40,6 +40,6 @@ struct fmt::formatter, wchar_t> : public fmt::formatter, wchar_t>::format(optional.value(), ctx); + return formatter::format(optional.value(), ctx); } }; From 07a68e3af1f2ff215f9c6a0f5fdc36374386f236 Mon Sep 17 00:00:00 2001 From: fabienfl Date: Fri, 3 May 2024 11:55:09 +0200 Subject: [PATCH 50/60] Revert "OrcLib: Text: Fmt: std_optional: forward to underlying type formatter" This is a PARTIAL revert This reverts commit e694f25853a1eed22a17d19679d15d4fa30951e7. --- src/OrcLib/Text/Fmt/std_optional.h | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/src/OrcLib/Text/Fmt/std_optional.h b/src/OrcLib/Text/Fmt/std_optional.h index 15b73f7a..28d6eee8 100644 --- a/src/OrcLib/Text/Fmt/std_optional.h +++ b/src/OrcLib/Text/Fmt/std_optional.h @@ -13,33 +13,31 @@ #include template -struct fmt::formatter> : public fmt::formatter +struct fmt::formatter> : public fmt::formatter { template - auto format(const std::optional& optional, FormatContext& ctx) -> decltype(ctx.out()) + auto format(const std::optional& optional, FormatContext& ctx) { if (!optional.has_value()) { - formatter na; - return na.format("N/A", ctx); + return fmt::formatter::format("N/A", ctx); } - return formatter::format(optional.value(), ctx); + return fmt::format_to(ctx.out(), "{}", *optional); } }; template -struct fmt::formatter, wchar_t> : public fmt::formatter +struct fmt::formatter, wchar_t> : public fmt::formatter { template - auto format(const std::optional& optional, FormatContext& ctx) -> decltype(ctx.out()) + auto format(const std::optional& optional, FormatContext& ctx) { if (!optional.has_value()) { - formatter na; - return na.format(L"N/A", ctx); + return fmt::formatter::format(L"N/A", ctx); } - return formatter::format(optional.value(), ctx); + return fmt::format_to(ctx.out(), L"{}", *optional); } }; From 43524569596cd9019d6be8ddb78a127ef49a6d93 Mon Sep 17 00:00:00 2001 From: fabienfl Date: Fri, 3 May 2024 12:01:49 +0200 Subject: [PATCH 51/60] OrcLib: Text: Fmt: make const specializations --- src/OrcCommand/Text/Fmt/WolfPriority.h | 4 ++-- src/OrcLib/Text/Fmt/BoolOnOff.h | 4 ++-- src/OrcLib/Text/Fmt/Boolean.h | 4 ++-- src/OrcLib/Text/Fmt/ByteQuantity.h | 4 ++-- .../Text/Fmt/CryptoHashStreamAlgorithm.h | 4 ++-- src/OrcLib/Text/Fmt/FILETIME.h | 4 ++-- src/OrcLib/Text/Fmt/FILE_NAME.h | 4 ++-- src/OrcLib/Text/Fmt/FSVBR.h | 4 ++-- .../Text/Fmt/FuzzyHashStreamAlgorithm.h | 4 ++-- src/OrcLib/Text/Fmt/Limit.h | 4 ++-- src/OrcLib/Text/Fmt/LocationType.h | 4 ++-- src/OrcLib/Text/Fmt/Offset.h | 4 ++-- src/OrcLib/Text/Fmt/OutputSpecTypes.h | 24 +++++++++---------- src/OrcLib/Text/Fmt/Partition.h | 4 ++-- src/OrcLib/Text/Fmt/PartitionFlags.h | 4 ++-- src/OrcLib/Text/Fmt/PartitionType.h | 4 ++-- src/OrcLib/Text/Fmt/Result.h | 8 +++---- src/OrcLib/Text/Fmt/SYSTEMTIME.h | 4 ++-- src/OrcLib/Text/Fmt/TimeUtc.h | 4 ++-- src/OrcLib/Text/Fmt/in_addr.h | 8 +++---- src/OrcLib/Text/Fmt/std_error_code.h | 4 ++-- src/OrcLib/Text/Fmt/std_optional.h | 4 ++-- 22 files changed, 58 insertions(+), 58 deletions(-) diff --git a/src/OrcCommand/Text/Fmt/WolfPriority.h b/src/OrcCommand/Text/Fmt/WolfPriority.h index 625cfe17..fb0283cd 100644 --- a/src/OrcCommand/Text/Fmt/WolfPriority.h +++ b/src/OrcCommand/Text/Fmt/WolfPriority.h @@ -19,7 +19,7 @@ template <> struct fmt::formatter : public fmt::formatter { template - auto format(const Orc::Command::Wolf::Main::WolfPriority& priority, FormatContext& ctx) -> decltype(ctx.out()) + auto format(const Orc::Command::Wolf::Main::WolfPriority& priority, FormatContext& ctx) const -> decltype(ctx.out()) { std::error_code ec; const auto utf8 = Orc::ToUtf8(Orc::Command::Wolf::Main::ToString(priority), ec); @@ -37,7 +37,7 @@ struct fmt::formatter : public fmt::formatter { template - auto format(Orc::Command::Wolf::Main::WolfPriority priority, FormatContext& ctx) -> decltype(ctx.out()) + auto format(Orc::Command::Wolf::Main::WolfPriority priority, FormatContext& ctx) const -> decltype(ctx.out()) { return formatter::format(Orc::Command::Wolf::Main::ToString(priority), ctx); } diff --git a/src/OrcLib/Text/Fmt/BoolOnOff.h b/src/OrcLib/Text/Fmt/BoolOnOff.h index dae1216b..97fdf1fc 100644 --- a/src/OrcLib/Text/Fmt/BoolOnOff.h +++ b/src/OrcLib/Text/Fmt/BoolOnOff.h @@ -17,7 +17,7 @@ template <> struct fmt::formatter : public fmt::formatter { template - auto format(const Orc::Traits::BoolOnOff& value, FormatContext& ctx) -> decltype(ctx.out()) + auto format(const Orc::Traits::BoolOnOff& value, FormatContext& ctx) const -> decltype(ctx.out()) { return formatter::format(value ? "On" : "Off", ctx); } @@ -27,7 +27,7 @@ template <> struct fmt::formatter : public fmt::formatter { template - auto format(const Orc::Traits::BoolOnOff& value, FormatContext& ctx) -> decltype(ctx.out()) + auto format(const Orc::Traits::BoolOnOff& value, FormatContext& ctx) const -> decltype(ctx.out()) { return formatter::format(value ? L"On" : L"Off", ctx); } diff --git a/src/OrcLib/Text/Fmt/Boolean.h b/src/OrcLib/Text/Fmt/Boolean.h index 195f6ca5..88bebe7b 100644 --- a/src/OrcLib/Text/Fmt/Boolean.h +++ b/src/OrcLib/Text/Fmt/Boolean.h @@ -17,7 +17,7 @@ template <> struct fmt::formatter : public fmt::formatter { template - auto format(const Orc::Traits::Boolean& value, FormatContext& ctx) -> decltype(ctx.out()) + auto format(const Orc::Traits::Boolean& value, FormatContext& ctx) const -> decltype(ctx.out()) { return formatter::format(value ? "True" : "False", ctx); } @@ -27,7 +27,7 @@ template <> struct fmt::formatter : public fmt::formatter { template - auto format(const Orc::Traits::Boolean& value, FormatContext& ctx) -> decltype(ctx.out()) + auto format(const Orc::Traits::Boolean& value, FormatContext& ctx) const -> decltype(ctx.out()) { return formatter::format(value ? L"True" : L"False", ctx); } diff --git a/src/OrcLib/Text/Fmt/ByteQuantity.h b/src/OrcLib/Text/Fmt/ByteQuantity.h index 7cf7613a..fce8c0a3 100644 --- a/src/OrcLib/Text/Fmt/ByteQuantity.h +++ b/src/OrcLib/Text/Fmt/ByteQuantity.h @@ -59,7 +59,7 @@ template struct fmt::formatter> : public fmt::formatter { template - auto format(const Orc::Traits::ByteQuantity& quantity, FormatContext& ctx) -> decltype(ctx.out()) + auto format(const Orc::Traits::ByteQuantity& quantity, FormatContext& ctx) const -> decltype(ctx.out()) { std::string s; FormatByteQuantityTo(std::back_inserter(s), quantity); @@ -71,7 +71,7 @@ template struct fmt::formatter, wchar_t> : public fmt::formatter { template - auto format(const Orc::Traits::ByteQuantity& quantity, FormatContext& ctx) -> decltype(ctx.out()) + auto format(const Orc::Traits::ByteQuantity& quantity, FormatContext& ctx) const -> decltype(ctx.out()) { std::wstring s; FormatByteQuantityToW(std::back_inserter(s), quantity); diff --git a/src/OrcLib/Text/Fmt/CryptoHashStreamAlgorithm.h b/src/OrcLib/Text/Fmt/CryptoHashStreamAlgorithm.h index 7f5d51f6..f058f358 100644 --- a/src/OrcLib/Text/Fmt/CryptoHashStreamAlgorithm.h +++ b/src/OrcLib/Text/Fmt/CryptoHashStreamAlgorithm.h @@ -16,7 +16,7 @@ template <> struct fmt::formatter : public fmt::formatter { template - auto format(const Orc::CryptoHashStreamAlgorithm& algs, FormatContext& ctx) -> decltype(ctx.out()) + auto format(const Orc::CryptoHashStreamAlgorithm& algs, FormatContext& ctx) const -> decltype(ctx.out()) { if (algs == Orc::CryptoHashStream::Algorithm::Undefined) { @@ -38,7 +38,7 @@ template <> struct fmt::formatter : public fmt::formatter { template - auto format(const Orc::CryptoHashStreamAlgorithm& algs, FormatContext& ctx) -> decltype(ctx.out()) + auto format(const Orc::CryptoHashStreamAlgorithm& algs, FormatContext& ctx) const -> decltype(ctx.out()) { if (algs == Orc::CryptoHashStream::Algorithm::Undefined) { diff --git a/src/OrcLib/Text/Fmt/FILETIME.h b/src/OrcLib/Text/Fmt/FILETIME.h index c9dd76c9..fb8c7349 100644 --- a/src/OrcLib/Text/Fmt/FILETIME.h +++ b/src/OrcLib/Text/Fmt/FILETIME.h @@ -15,7 +15,7 @@ template <> struct fmt::formatter : public fmt::formatter { template - auto format(const FILETIME& ft, FormatContext& ctx) -> decltype(ctx.out()) + auto format(const FILETIME& ft, FormatContext& ctx) const -> decltype(ctx.out()) { SYSTEMTIME stUTC {0}; if (FileTimeToSystemTime(&ft, &stUTC)) @@ -28,7 +28,7 @@ template <> struct fmt::formatter : public fmt::formatter { template - auto format(const FILETIME& ft, FormatContext& ctx) -> decltype(ctx.out()) + auto format(const FILETIME& ft, FormatContext& ctx) const -> decltype(ctx.out()) { SYSTEMTIME stUTC {0}; if (FileTimeToSystemTime(&ft, &stUTC)) diff --git a/src/OrcLib/Text/Fmt/FILE_NAME.h b/src/OrcLib/Text/Fmt/FILE_NAME.h index 63bcca9a..03f83bf5 100644 --- a/src/OrcLib/Text/Fmt/FILE_NAME.h +++ b/src/OrcLib/Text/Fmt/FILE_NAME.h @@ -14,7 +14,7 @@ template <> struct fmt::formatter : public fmt::formatter { template - auto format(const FILE_NAME& fileName, FormatContext& ctx) -> decltype(ctx.out()) + auto format(const FILE_NAME& fileName, FormatContext& ctx) const -> decltype(ctx.out()) { std::error_code ec; @@ -32,7 +32,7 @@ template <> struct fmt::formatter : public fmt::formatter { template - auto format(const FILE_NAME& fileName, FormatContext& ctx) -> decltype(ctx.out()) + auto format(const FILE_NAME& fileName, FormatContext& ctx) const -> decltype(ctx.out()) { const auto name = std::wstring_view(fileName.FileName, fileName.FileNameLength); return formatter::format(name, ctx); diff --git a/src/OrcLib/Text/Fmt/FSVBR.h b/src/OrcLib/Text/Fmt/FSVBR.h index 09be64b8..ad70d6b5 100644 --- a/src/OrcLib/Text/Fmt/FSVBR.h +++ b/src/OrcLib/Text/Fmt/FSVBR.h @@ -17,7 +17,7 @@ template <> struct fmt::formatter : public fmt::formatter { template - auto format(const Orc::FSVBR_FSType& FSType, FormatContext& ctx) -> decltype(ctx.out()) + auto format(const Orc::FSVBR_FSType& FSType, FormatContext& ctx) const -> decltype(ctx.out()) { const auto utf16 = Orc::ToString(FSType); @@ -36,7 +36,7 @@ template <> struct fmt::formatter : public fmt::formatter { template - auto format(const Orc::FSVBR_FSType& FSType, FormatContext& ctx) -> decltype(ctx.out()) + auto format(const Orc::FSVBR_FSType& FSType, FormatContext& ctx) const -> decltype(ctx.out()) { return formatter::format(Orc::ToString(FSType), ctx); } diff --git a/src/OrcLib/Text/Fmt/FuzzyHashStreamAlgorithm.h b/src/OrcLib/Text/Fmt/FuzzyHashStreamAlgorithm.h index be8e6fa4..893643b2 100644 --- a/src/OrcLib/Text/Fmt/FuzzyHashStreamAlgorithm.h +++ b/src/OrcLib/Text/Fmt/FuzzyHashStreamAlgorithm.h @@ -16,7 +16,7 @@ template <> struct fmt::formatter : public fmt::formatter { template - auto format(const Orc::FuzzyHashStreamAlgorithm& algs, FormatContext& ctx) -> decltype(ctx.out()) + auto format(const Orc::FuzzyHashStreamAlgorithm& algs, FormatContext& ctx) const -> decltype(ctx.out()) { if (algs == Orc::FuzzyHashStreamAlgorithm::Undefined) { @@ -38,7 +38,7 @@ template <> struct fmt::formatter : public fmt::formatter { template - auto format(const Orc::FuzzyHashStreamAlgorithm& algs, FormatContext& ctx) -> decltype(ctx.out()) + auto format(const Orc::FuzzyHashStreamAlgorithm& algs, FormatContext& ctx) const -> decltype(ctx.out()) { if (algs == Orc::FuzzyHashStreamAlgorithm::Undefined) { diff --git a/src/OrcLib/Text/Fmt/Limit.h b/src/OrcLib/Text/Fmt/Limit.h index b86f2cdd..ecc7d0a2 100644 --- a/src/OrcLib/Text/Fmt/Limit.h +++ b/src/OrcLib/Text/Fmt/Limit.h @@ -16,7 +16,7 @@ template struct fmt::formatter> : public fmt::formatter { template - auto format(const Orc::Limit& limit, FormatContext& ctx) -> decltype(ctx.out()) + auto format(const Orc::Limit& limit, FormatContext& ctx) const -> decltype(ctx.out()) { if (limit.IsUnlimited()) { @@ -32,7 +32,7 @@ template struct fmt::formatter, wchar_t> : public fmt::formatter { template - auto format(const Orc::Limit& limit, FormatContext& ctx) -> decltype(ctx.out()) + auto format(const Orc::Limit& limit, FormatContext& ctx) const -> decltype(ctx.out()) { if (limit.IsUnlimited()) { diff --git a/src/OrcLib/Text/Fmt/LocationType.h b/src/OrcLib/Text/Fmt/LocationType.h index 70b1e74a..eaf3f07c 100644 --- a/src/OrcLib/Text/Fmt/LocationType.h +++ b/src/OrcLib/Text/Fmt/LocationType.h @@ -17,7 +17,7 @@ template <> struct fmt::formatter : public fmt::formatter { template - auto format(const Orc::LocationType& type, FormatContext& ctx) -> decltype(ctx.out()) + auto format(const Orc::LocationType& type, FormatContext& ctx) const -> decltype(ctx.out()) { std::error_code ec; const auto utf8 = Orc::ToUtf8(Orc::ToString(type), ec); @@ -34,7 +34,7 @@ template <> struct fmt::formatter : public fmt::formatter { template - auto format(const Orc::LocationType& type, FormatContext& ctx) -> decltype(ctx.out()) + auto format(const Orc::LocationType& type, FormatContext& ctx) const -> decltype(ctx.out()) { return formatter::format(Orc::ToString(type), ctx); } diff --git a/src/OrcLib/Text/Fmt/Offset.h b/src/OrcLib/Text/Fmt/Offset.h index 6bf590ad..a007e55f 100644 --- a/src/OrcLib/Text/Fmt/Offset.h +++ b/src/OrcLib/Text/Fmt/Offset.h @@ -50,7 +50,7 @@ template struct fmt::formatter> : public fmt::formatter { template - auto format(const Orc::Traits::Offset& offset, FormatContext& ctx) -> decltype(ctx.out()) + auto format(const Orc::Traits::Offset& offset, FormatContext& ctx) const -> decltype(ctx.out()) { std::string s; FormatOffsetTo(std::back_inserter(s), offset); @@ -62,7 +62,7 @@ template struct fmt::formatter, wchar_t> : public fmt::formatter { template - auto format(const Orc::Traits::Offset& offset, FormatContext& ctx) -> decltype(ctx.out()) + auto format(const Orc::Traits::Offset& offset, FormatContext& ctx) const -> decltype(ctx.out()) { std::wstring s; FormatOffsetToW(std::back_inserter(s), offset); diff --git a/src/OrcLib/Text/Fmt/OutputSpecTypes.h b/src/OrcLib/Text/Fmt/OutputSpecTypes.h index f3b19282..f205867f 100644 --- a/src/OrcLib/Text/Fmt/OutputSpecTypes.h +++ b/src/OrcLib/Text/Fmt/OutputSpecTypes.h @@ -18,7 +18,7 @@ template <> struct fmt::formatter : public fmt::formatter { template - auto format(const Orc::OutputSpecTypes::UploadAuthScheme& scheme, FormatContext& ctx) -> decltype(ctx.out()) + auto format(const Orc::OutputSpecTypes::UploadAuthScheme& scheme, FormatContext& ctx) const -> decltype(ctx.out()) { std::error_code ec; const auto utf8 = Orc::ToUtf8(Orc::ToString(scheme), ec); @@ -36,7 +36,7 @@ struct fmt::formatter : public fmt::formatter { template - auto format(const Orc::OutputSpecTypes::UploadAuthScheme& scheme, FormatContext& ctx) -> decltype(ctx.out()) + auto format(const Orc::OutputSpecTypes::UploadAuthScheme& scheme, FormatContext& ctx) const -> decltype(ctx.out()) { return formatter::format(Orc::ToString(scheme), ctx); } @@ -46,7 +46,7 @@ template <> struct fmt::formatter : public fmt::formatter { template - auto format(const Orc::OutputSpecTypes::UploadMethod& method, FormatContext& ctx) -> decltype(ctx.out()) + auto format(const Orc::OutputSpecTypes::UploadMethod& method, FormatContext& ctx) const -> decltype(ctx.out()) { std::error_code ec; const auto utf8 = Orc::ToUtf8(Orc::ToString(method), ec); @@ -63,7 +63,7 @@ template <> struct fmt::formatter : public fmt::formatter { template - auto format(const Orc::OutputSpecTypes::UploadMethod& method, FormatContext& ctx) -> decltype(ctx.out()) + auto format(const Orc::OutputSpecTypes::UploadMethod& method, FormatContext& ctx) const -> decltype(ctx.out()) { return formatter::format(Orc::ToString(method), ctx); } @@ -73,7 +73,7 @@ template <> struct fmt::formatter : public fmt::formatter { template - auto format(const Orc::OutputSpecTypes::UploadOperation& operation, FormatContext& ctx) -> decltype(ctx.out()) + auto format(const Orc::OutputSpecTypes::UploadOperation& operation, FormatContext& ctx) const -> decltype(ctx.out()) { std::error_code ec; const auto utf8 = Orc::ToUtf8(Orc::ToString(operation), ec); @@ -91,7 +91,7 @@ struct fmt::formatter : public fmt::formatter { template - auto format(const Orc::OutputSpecTypes::UploadOperation& operation, FormatContext& ctx) -> decltype(ctx.out()) + auto format(const Orc::OutputSpecTypes::UploadOperation& operation, FormatContext& ctx) const -> decltype(ctx.out()) { return formatter::format(Orc::ToString(operation), ctx); } @@ -101,7 +101,7 @@ template <> struct fmt::formatter : public fmt::formatter { template - auto format(const Orc::OutputSpecTypes::UploadMode& mode, FormatContext& ctx) -> decltype(ctx.out()) + auto format(const Orc::OutputSpecTypes::UploadMode& mode, FormatContext& ctx) const -> decltype(ctx.out()) { std::error_code ec; const auto utf8 = Orc::ToUtf8(Orc::ToString(mode), ec); @@ -118,7 +118,7 @@ template <> struct fmt::formatter : public fmt::formatter { template - auto format(const Orc::OutputSpecTypes::UploadMode& mode, FormatContext& ctx) -> decltype(ctx.out()) + auto format(const Orc::OutputSpecTypes::UploadMode& mode, FormatContext& ctx) const -> decltype(ctx.out()) { return formatter::format(Orc::ToString(mode), ctx); } @@ -128,7 +128,7 @@ template <> struct fmt::formatter : public fmt::formatter { template - auto format(const Orc::OutputSpecTypes::Encoding& encoding, FormatContext& ctx) -> decltype(ctx.out()) + auto format(const Orc::OutputSpecTypes::Encoding& encoding, FormatContext& ctx) const -> decltype(ctx.out()) { std::error_code ec; const auto utf8 = Orc::ToUtf8(Orc::ToString(encoding), ec); @@ -145,7 +145,7 @@ template <> struct fmt::formatter : public fmt::formatter { template - auto format(const Orc::OutputSpecTypes::Encoding& encoding, FormatContext& ctx) -> decltype(ctx.out()) + auto format(const Orc::OutputSpecTypes::Encoding& encoding, FormatContext& ctx) const -> decltype(ctx.out()) { return formatter::format(Orc::ToString(encoding), ctx); } @@ -155,7 +155,7 @@ template <> struct fmt::formatter : public fmt::formatter { template - auto format(const Orc::OutputSpecTypes::Kind& kind, FormatContext& ctx) -> decltype(ctx.out()) + auto format(const Orc::OutputSpecTypes::Kind& kind, FormatContext& ctx) const -> decltype(ctx.out()) { std::error_code ec; const auto utf8 = Orc::ToUtf8(Orc::ToString(kind), ec); @@ -172,7 +172,7 @@ template <> struct fmt::formatter : public fmt::formatter { template - auto format(const Orc::OutputSpecTypes::Kind& kind, FormatContext& ctx) -> decltype(ctx.out()) + auto format(const Orc::OutputSpecTypes::Kind& kind, FormatContext& ctx) const -> decltype(ctx.out()) { return formatter::format(Orc::ToString(kind), ctx); } diff --git a/src/OrcLib/Text/Fmt/Partition.h b/src/OrcLib/Text/Fmt/Partition.h index 16b531ca..3a0a245b 100644 --- a/src/OrcLib/Text/Fmt/Partition.h +++ b/src/OrcLib/Text/Fmt/Partition.h @@ -16,7 +16,7 @@ template <> struct fmt::formatter : public fmt::formatter { template - auto format(const Orc::Partition& partition, FormatContext& ctx) -> decltype(ctx.out()) + auto format(const Orc::Partition& partition, FormatContext& ctx) const -> decltype(ctx.out()) { std::error_code ec; const auto utf8 = Orc::ToUtf8(Orc::ToString(partition), ec); @@ -33,7 +33,7 @@ template <> struct fmt::formatter : public fmt::formatter { template - auto format(const Orc::Partition& partition, FormatContext& ctx) -> decltype(ctx.out()) + auto format(const Orc::Partition& partition, FormatContext& ctx) const -> decltype(ctx.out()) { return formatter::format(Orc::ToString(partition), ctx); } diff --git a/src/OrcLib/Text/Fmt/PartitionFlags.h b/src/OrcLib/Text/Fmt/PartitionFlags.h index e948b70d..5dc76c4a 100644 --- a/src/OrcLib/Text/Fmt/PartitionFlags.h +++ b/src/OrcLib/Text/Fmt/PartitionFlags.h @@ -16,7 +16,7 @@ template <> struct fmt::formatter : public fmt::formatter { template - auto format(const Orc::PartitionFlags& flags, FormatContext& ctx) -> decltype(ctx.out()) + auto format(const Orc::PartitionFlags& flags, FormatContext& ctx) const -> decltype(ctx.out()) { std::error_code ec; const auto utf8 = Orc::ToUtf8(Orc::ToString(flags), ec); @@ -33,7 +33,7 @@ template <> struct fmt::formatter : public fmt::formatter { template - auto format(const Orc::PartitionFlags& flags, FormatContext& ctx) -> decltype(ctx.out()) + auto format(const Orc::PartitionFlags& flags, FormatContext& ctx) const -> decltype(ctx.out()) { return formatter::format(Orc::ToString(flags), ctx); } diff --git a/src/OrcLib/Text/Fmt/PartitionType.h b/src/OrcLib/Text/Fmt/PartitionType.h index 13bda68d..a0b5919b 100644 --- a/src/OrcLib/Text/Fmt/PartitionType.h +++ b/src/OrcLib/Text/Fmt/PartitionType.h @@ -16,7 +16,7 @@ template <> struct fmt::formatter : public fmt::formatter { template - auto format(const Orc::PartitionType& type, FormatContext& ctx) -> decltype(ctx.out()) + auto format(const Orc::PartitionType& type, FormatContext& ctx) const -> decltype(ctx.out()) { std::error_code ec; const auto utf8 = Orc::ToUtf8(Orc::ToString(type), ec); @@ -33,7 +33,7 @@ template <> struct fmt::formatter : public fmt::formatter { template - auto format(const Orc::PartitionType& type, FormatContext& ctx) -> decltype(ctx.out()) + auto format(const Orc::PartitionType& type, FormatContext& ctx) const -> decltype(ctx.out()) { return formatter::format(Orc::ToString(type), ctx); } diff --git a/src/OrcLib/Text/Fmt/Result.h b/src/OrcLib/Text/Fmt/Result.h index d2e17dce..71b3c43a 100644 --- a/src/OrcLib/Text/Fmt/Result.h +++ b/src/OrcLib/Text/Fmt/Result.h @@ -17,7 +17,7 @@ template struct fmt::formatter> : public fmt::formatter { template - auto format(const Orc::Result& result, FormatContext& ctx) -> decltype(ctx.out()) + auto format(const Orc::Result& result, FormatContext& ctx) const -> decltype(ctx.out()) { if (result.has_error()) { @@ -33,7 +33,7 @@ template <> struct fmt::formatter> : public fmt::formatter { template - auto format(const Orc::Result& result, FormatContext& ctx) -> decltype(ctx.out()) + auto format(const Orc::Result& result, FormatContext& ctx) const -> decltype(ctx.out()) { if (result.has_error()) { @@ -49,7 +49,7 @@ template struct fmt::formatter, wchar_t> : public fmt::formatter { template - auto format(const Orc::Result& result, FormatContext& ctx) -> decltype(ctx.out()) + auto format(const Orc::Result& result, FormatContext& ctx) const -> decltype(ctx.out()) { if (result.has_error()) { @@ -65,7 +65,7 @@ template <> struct fmt::formatter, wchar_t> : public fmt::formatter { template - auto format(const Orc::Result& result, FormatContext& ctx) -> decltype(ctx.out()) + auto format(const Orc::Result& result, FormatContext& ctx) const -> decltype(ctx.out()) { if (result.has_error()) { diff --git a/src/OrcLib/Text/Fmt/SYSTEMTIME.h b/src/OrcLib/Text/Fmt/SYSTEMTIME.h index cd215963..1b5fe987 100644 --- a/src/OrcLib/Text/Fmt/SYSTEMTIME.h +++ b/src/OrcLib/Text/Fmt/SYSTEMTIME.h @@ -46,7 +46,7 @@ template <> struct fmt::formatter : public fmt::formatter { template - auto format(const SYSTEMTIME& st, FormatContext& ctx) -> decltype(ctx.out()) + auto format(const SYSTEMTIME& st, FormatContext& ctx) const -> decltype(ctx.out()) { return formatter::format(Orc::Text::FormatSystemTimeA(st), ctx); } @@ -56,7 +56,7 @@ template <> struct fmt::formatter : public fmt::formatter { template - auto format(const SYSTEMTIME& st, FormatContext& ctx) -> decltype(ctx.out()) + auto format(const SYSTEMTIME& st, FormatContext& ctx) const -> decltype(ctx.out()) { return formatter::format(Orc::Text::FormatSystemTimeW(st), ctx); } diff --git a/src/OrcLib/Text/Fmt/TimeUtc.h b/src/OrcLib/Text/Fmt/TimeUtc.h index 1172008e..2bb990f0 100644 --- a/src/OrcLib/Text/Fmt/TimeUtc.h +++ b/src/OrcLib/Text/Fmt/TimeUtc.h @@ -52,7 +52,7 @@ template struct fmt::formatter> : public fmt::formatter { template - auto format(const Orc::Traits::TimeUtc& time, FormatContext& ctx) -> decltype(ctx.out()) + auto format(const Orc::Traits::TimeUtc& time, FormatContext& ctx) const -> decltype(ctx.out()) { std::string s = Orc::Text::FormatSystemTimeUtcA(time); return formatter::format(s, ctx); @@ -63,7 +63,7 @@ template struct fmt::formatter, wchar_t> : public fmt::formatter { template - auto format(const Orc::Traits::TimeUtc& time, FormatContext& ctx) -> decltype(ctx.out()) + auto format(const Orc::Traits::TimeUtc& time, FormatContext& ctx) const -> decltype(ctx.out()) { std::wstring s = Orc::Text::FormatSystemTimeUtcW(time); return formatter::format(s, ctx); diff --git a/src/OrcLib/Text/Fmt/in_addr.h b/src/OrcLib/Text/Fmt/in_addr.h index 3aa7bb2a..3ff085fd 100644 --- a/src/OrcLib/Text/Fmt/in_addr.h +++ b/src/OrcLib/Text/Fmt/in_addr.h @@ -21,7 +21,7 @@ template <> struct fmt::formatter : public fmt::formatter { template - auto format(const in_addr& ip, FormatContext& ctx) -> decltype(ctx.out()) + auto format(const in_addr& ip, FormatContext& ctx) const -> decltype(ctx.out()) { auto s = Orc::ToString(ip).value_or(fmt_in_addr::kNotApplicable); return formatter::format(s, ctx); @@ -32,7 +32,7 @@ template <> struct fmt::formatter : public fmt::formatter { template - auto format(const in_addr& ip, FormatContext& ctx) -> decltype(ctx.out()) + auto format(const in_addr& ip, FormatContext& ctx) const -> decltype(ctx.out()) { auto s = Orc::ToWString(ip).value_or(fmt_in_addr::kNotApplicableW); return formatter::format(s, ctx); @@ -43,7 +43,7 @@ template <> struct fmt::formatter : public fmt::formatter { template - auto format(const in6_addr& ip, FormatContext& ctx) -> decltype(ctx.out()) + auto format(const in6_addr& ip, FormatContext& ctx) const -> decltype(ctx.out()) { auto s = Orc::ToString(ip).value_or(fmt_in_addr::kNotApplicable); return formatter::format(s, ctx); @@ -54,7 +54,7 @@ template <> struct fmt::formatter : public fmt::formatter { template - auto format(const in6_addr& ip, FormatContext& ctx) -> decltype(ctx.out()) + auto format(const in6_addr& ip, FormatContext& ctx) const -> decltype(ctx.out()) { auto s = Orc::ToWString(ip).value_or(fmt_in_addr::kNotApplicableW); return formatter::format(s, ctx); diff --git a/src/OrcLib/Text/Fmt/std_error_code.h b/src/OrcLib/Text/Fmt/std_error_code.h index 849a5161..635c3a40 100644 --- a/src/OrcLib/Text/Fmt/std_error_code.h +++ b/src/OrcLib/Text/Fmt/std_error_code.h @@ -19,7 +19,7 @@ template <> struct fmt::formatter : public fmt::formatter { template - auto format(const std::error_code& ec, FormatContext& ctx) -> decltype(ctx.out()) + auto format(const std::error_code& ec, FormatContext& ctx) const -> decltype(ctx.out()) { std::string s; @@ -52,7 +52,7 @@ template <> struct fmt::formatter : public fmt::formatter { template - auto format(const std::error_code& ec, FormatContext& ctx) -> decltype(ctx.out()) + auto format(const std::error_code& ec, FormatContext& ctx) const -> decltype(ctx.out()) { std::wstring s; diff --git a/src/OrcLib/Text/Fmt/std_optional.h b/src/OrcLib/Text/Fmt/std_optional.h index 28d6eee8..a513b5f1 100644 --- a/src/OrcLib/Text/Fmt/std_optional.h +++ b/src/OrcLib/Text/Fmt/std_optional.h @@ -16,7 +16,7 @@ template struct fmt::formatter> : public fmt::formatter { template - auto format(const std::optional& optional, FormatContext& ctx) + auto format(const std::optional& optional, FormatContext& ctx) const { if (!optional.has_value()) { @@ -31,7 +31,7 @@ template struct fmt::formatter, wchar_t> : public fmt::formatter { template - auto format(const std::optional& optional, FormatContext& ctx) + auto format(const std::optional& optional, FormatContext& ctx) const { if (!optional.has_value()) { From d76d5a66b0f48f6b9cf478c33804be0604643c4e Mon Sep 17 00:00:00 2001 From: fabienfl Date: Wed, 15 May 2024 16:37:04 +0200 Subject: [PATCH 52/60] OrcLib: SystemDetails: SetOrcComputerName: replace spaces with '_' --- src/OrcLib/SystemDetails.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/OrcLib/SystemDetails.cpp b/src/OrcLib/SystemDetails.cpp index 1c8a5eb1..ded5bb84 100644 --- a/src/OrcLib/SystemDetails.cpp +++ b/src/OrcLib/SystemDetails.cpp @@ -809,7 +809,9 @@ HRESULT Orc::SystemDetails::SetOrcComputerName(const std::wstring& strComputerNa if (FAILED(hr = LoadSystemDetails())) return hr; - g_pDetailsBlock->strOrcComputerName = strComputerName; + std::wstring name = strComputerName; + std::replace(std::begin(name), std::end(name), L' ', L'_'); + g_pDetailsBlock->strOrcComputerName = std::move(name); if (!SetEnvironmentVariableW(OrcComputerName, g_pDetailsBlock->strOrcComputerName.value().c_str())) return HRESULT_FROM_WIN32(GetLastError()); From e1a01d824305479caefcac8922bf6dec4c0181a9 Mon Sep 17 00:00:00 2001 From: fabienfl Date: Thu, 30 May 2024 13:32:49 +0200 Subject: [PATCH 53/60] OrcCommand: WolfLauncher: fix cpu weight configuration --- src/OrcCommand/Command/WolfLauncher/WolfExecution_Config.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/OrcCommand/Command/WolfLauncher/WolfExecution_Config.cpp b/src/OrcCommand/Command/WolfLauncher/WolfExecution_Config.cpp index 84aae27a..250ce7d2 100644 --- a/src/OrcCommand/Command/WolfLauncher/WolfExecution_Config.cpp +++ b/src/OrcCommand/Command/WolfLauncher/WolfExecution_Config.cpp @@ -686,7 +686,7 @@ HRESULT WolfExecution::SetRestrictionsFromConfig(const ConfigItem& item) else if (item[WOLFLAUNCHER_CPU_WEIGHT]) { DWORD weight = 0; - if (FAILED(hr = GetIntegerFromArg(item[WOLFLAUNCHER_CPU_RATE].c_str(), weight))) + if (FAILED(hr = GetIntegerFromArg(item[WOLFLAUNCHER_CPU_WEIGHT].c_str(), weight))) return hr; if (!m_Restrictions.CpuRateControl) From 2ebe99aeafd44766ed18d3e174ab5888e61ab8fc Mon Sep 17 00:00:00 2001 From: fabienfl Date: Thu, 30 May 2024 13:34:23 +0200 Subject: [PATCH 54/60] OrcCommand: WolfLauncher: add log to SetRestrictionsFromConfig --- .../WolfLauncher/WolfExecution_Config.cpp | 35 ++++++++++++ src/OrcLib/ParameterCheck.cpp | 56 +++++++++++++++++++ 2 files changed, 91 insertions(+) diff --git a/src/OrcCommand/Command/WolfLauncher/WolfExecution_Config.cpp b/src/OrcCommand/Command/WolfLauncher/WolfExecution_Config.cpp index 250ce7d2..3f4aeab7 100644 --- a/src/OrcCommand/Command/WolfLauncher/WolfExecution_Config.cpp +++ b/src/OrcCommand/Command/WolfLauncher/WolfExecution_Config.cpp @@ -558,7 +558,12 @@ HRESULT WolfExecution::SetRestrictionsFromConfig(const ConfigItem& item) { LARGE_INTEGER li; if (FAILED(hr = GetFileSizeFromArg(item[WOLFLAUNCHER_JOBMEMORY].c_str(), li))) + { + Log::Debug( + L"Failed GetFileSizeFromArg on WOLFLAUNCHER_JOBMEMORY (value: {})", + item[WOLFLAUNCHER_JOBMEMORY].c_str()); return hr; + } if (arch == PROCESSOR_ARCHITECTURE_INTEL && li.QuadPart > MAXDWORD) { @@ -581,7 +586,12 @@ HRESULT WolfExecution::SetRestrictionsFromConfig(const ConfigItem& item) { LARGE_INTEGER li; if (FAILED(hr = GetFileSizeFromArg(item[WOLFLAUNCHER_PROCESSMEMORY].c_str(), li))) + { + Log::Debug( + L"Failed GetFileSizeFromArg on WOLFLAUNCHER_PROCESSMEMORY (value: {})", + item[WOLFLAUNCHER_PROCESSMEMORY].c_str()); return hr; + } if (arch == PROCESSOR_ARCHITECTURE_INTEL && li.QuadPart > MAXDWORD) { @@ -605,7 +615,12 @@ HRESULT WolfExecution::SetRestrictionsFromConfig(const ConfigItem& item) { LARGE_INTEGER li; if (FAILED(hr = GetIntegerFromArg(item[WOLFLAUNCHER_ELAPSEDTIME].c_str(), li))) + { + Log::Debug( + L"Failed GetIntegerFromArg on WOLFLAUNCHER_ELAPSEDTIME (value: {})", + item[WOLFLAUNCHER_ELAPSEDTIME].c_str()); return hr; + } if (arch == PROCESSOR_ARCHITECTURE_INTEL && li.QuadPart > MAXDWORD) { @@ -620,7 +635,12 @@ HRESULT WolfExecution::SetRestrictionsFromConfig(const ConfigItem& item) { LARGE_INTEGER li; if (FAILED(hr = GetIntegerFromArg(item[WOLFLAUNCHER_JOBUSERTIME].c_str(), li))) + { + Log::Debug( + L"Failed GetIntegerFromArg on WOLFLAUNCHER_JOBUSERTIME (value: {})", + item[WOLFLAUNCHER_JOBUSERTIME].c_str()); return hr; + } if (arch == PROCESSOR_ARCHITECTURE_INTEL && li.QuadPart > MAXDWORD) { @@ -643,7 +663,12 @@ HRESULT WolfExecution::SetRestrictionsFromConfig(const ConfigItem& item) { LARGE_INTEGER li; if (FAILED(hr = GetIntegerFromArg(item[WOLFLAUNCHER_PERPROCESSUSERTIME].c_str(), li))) + { + Log::Debug( + L"Failed GetIntegerFromArg on WOLFLAUNCHER_PERPROCESSUSERTIME (value: {})", + item[WOLFLAUNCHER_PERPROCESSUSERTIME].c_str()); return hr; + } if (arch == PROCESSOR_ARCHITECTURE_INTEL && li.QuadPart > MAXDWORD) { @@ -671,7 +696,12 @@ HRESULT WolfExecution::SetRestrictionsFromConfig(const ConfigItem& item) { DWORD percentage = 0; if (FAILED(hr = GetPercentageFromArg(item[WOLFLAUNCHER_CPU_RATE].c_str(), percentage))) + { + Log::Debug( + L"Failed GetPercentageFromArg on WOLFLAUNCHER_CPU_RATE (value: {})", + item[WOLFLAUNCHER_CPU_RATE].c_str()); return hr; + } if (!m_Restrictions.CpuRateControl) { @@ -687,7 +717,12 @@ HRESULT WolfExecution::SetRestrictionsFromConfig(const ConfigItem& item) { DWORD weight = 0; if (FAILED(hr = GetIntegerFromArg(item[WOLFLAUNCHER_CPU_WEIGHT].c_str(), weight))) + { + Log::Debug( + L"Failed GetIntegerFromArg on WOLFLAUNCHER_CPU_WEIGHT (value: {})", + item[WOLFLAUNCHER_CPU_WEIGHT].c_str()); return hr; + } if (!m_Restrictions.CpuRateControl) { diff --git a/src/OrcLib/ParameterCheck.cpp b/src/OrcLib/ParameterCheck.cpp index 2f6369d1..45719150 100644 --- a/src/OrcLib/ParameterCheck.cpp +++ b/src/OrcLib/ParameterCheck.cpp @@ -608,6 +608,7 @@ HRESULT Orc::GetFileSizeFromArg(const WCHAR* pSize, LARGE_INTEGER& size) } if (dwLen > ORC_MAX_PATH) { + Log::Debug("GetFileSizeFromArg: unexpected argument value (expected: <={}, actual: {})", ORC_MAX_PATH, dwLen); return E_INVALIDARG; } @@ -641,7 +642,10 @@ HRESULT Orc::GetFileSizeFromArg(const WCHAR* pSize, LARGE_INTEGER& size) size.QuadPart = _wtoi64(szTemp) * dwMultiplier; if (errno == ERANGE) + { + Log::Debug(L"GetFileSizeFromArg: failed _wtoi64 (input: {})", szTemp); return E_INVALIDARG; + } return S_OK; } @@ -649,7 +653,10 @@ HRESULT Orc::GetFileSizeFromArg(const WCHAR* pSize, LARGE_INTEGER& size) HRESULT Orc::GetPercentageFromArg(const WCHAR* pStr, DWORD& value) { if (pStr == nullptr) + { + Log::Debug(L"GetPercentageFromArg: invalid nullptr"); return E_POINTER; + } std::wstring_view str(pStr); @@ -663,7 +670,17 @@ HRESULT Orc::GetPercentageFromArg(const WCHAR* pStr, DWORD& value) return E_INVALIDARG; if (errno == ERANGE || value == 0) + { + if (errno == ERANGE) + { + Log::Debug(L"GetPercentageFromArg: failed _wtoi64 (input: {})", pStr); + } + else + { + Log::Debug(L"GetPercentageFromArg: failed because _size=0"); + } return E_INVALIDARG; + } try { @@ -671,6 +688,7 @@ HRESULT Orc::GetPercentageFromArg(const WCHAR* pStr, DWORD& value) } catch (const std::overflow_error&) { + Log::Debug(L"GetPercentageFromArg: failed because overflow error (input: {})", _value); return E_INVALIDARG; } return S_OK; @@ -682,7 +700,10 @@ HRESULT Orc::GetIntegerFromArg(const WCHAR* pSize, LARGE_INTEGER& size) size.LowPart = 0L; if (pSize == nullptr) + { + Log::Debug(L"GetIntegerFromArg (LARGE_INTEGER): invalid nullptr"); return E_POINTER; + } size.QuadPart = _wtoi64(pSize); @@ -692,13 +713,19 @@ HRESULT Orc::GetIntegerFromArg(const WCHAR* pSize, LARGE_INTEGER& size) while (*pCur) { if (*pCur != L'0') + { + Log::Debug(L"GetIntegerFromArg (LARGE_INTEGER): check '0' loop failed (intput: {})", pSize); return E_INVALIDARG; + } pCur++; } } if (errno == ERANGE || errno == EINVAL) + { + Log::Debug(L"GetIntegerFromArg (LARGE_INTEGER): failed _wtoi64 (input: {})", pSize); return E_INVALIDARG; + } return S_OK; } @@ -706,18 +733,33 @@ HRESULT Orc::GetIntegerFromArg(const WCHAR* pSize, LARGE_INTEGER& size) HRESULT Orc::GetIntegerFromArg(const WCHAR* pStr, size_t& size) { if (pStr == nullptr) + { + Log::Debug(L"GetIntegerFromArg (size_t): invalid nullptr"); return E_POINTER; + } auto _size = _wtoi(pStr); if (errno == ERANGE || _size == 0) + { + if (errno == ERANGE) + { + Log::Debug(L"GetIntegerFromArg (size_t): failed _wtoi64 (input: {})", pStr); + } + else + { + Log::Debug(L"GetIntegerFromArg (size_t): failed because _size=0"); + } return E_INVALIDARG; + } + try { size = ConvertTo(_size); } catch (const std::overflow_error&) { + Log::Debug(L"GetIntegerFromArg (size_t): failed because overflow error (input: {})", _size); return E_INVALIDARG; } return S_OK; @@ -726,12 +768,25 @@ HRESULT Orc::GetIntegerFromArg(const WCHAR* pStr, size_t& size) HRESULT Orc::GetIntegerFromArg(const WCHAR* pStr, DWORD& value) { if (pStr == nullptr) + { + Log::Debug(L"GetIntegerFromArg (DWORD): invalid nullptr"); return E_POINTER; + } auto _value = _wtoi(pStr); if (errno == ERANGE || _value == 0) + { + if (errno == ERANGE) + { + Log::Debug(L"GetIntegerFromArg (DWORD): failed _wtoi64 (input: {})", pStr); + } + else + { + Log::Debug(L"GetIntegerFromArg (DWORD): failed because _size=0"); + } return E_INVALIDARG; + } try { @@ -739,6 +794,7 @@ HRESULT Orc::GetIntegerFromArg(const WCHAR* pStr, DWORD& value) } catch (const std::overflow_error&) { + Log::Debug(L"GetIntegerFromArg (DWORD): failed because overflow error (input: {})", _value); return E_INVALIDARG; } From ff4f7e487ba2574e9872f7de3a45f32dd35ef257 Mon Sep 17 00:00:00 2001 From: fabienfl Date: Fri, 31 May 2024 14:54:00 +0200 Subject: [PATCH 55/60] OrcLib: SystemDetail: add tags for W11 23H2 --- src/OrcLib/SystemDetails.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/OrcLib/SystemDetails.cpp b/src/OrcLib/SystemDetails.cpp index ded5bb84..0934e146 100644 --- a/src/OrcLib/SystemDetails.cpp +++ b/src/OrcLib/SystemDetails.cpp @@ -232,6 +232,7 @@ bool SystemDetails::IsKnownWindowsBuild(uint32_t build) { switch (build) { + case 22631: case 22621: case 22000: case 20348: @@ -281,6 +282,10 @@ void SystemDetails::GetTagsFromBuildId(uint32_t ProductType, uint32_t build, Sys switch (build) { + case 22631: + tags.insert(L"Windows11"); + tags.insert(L"Release#23H2"); + break; case 22621: tags.insert(L"Windows11"); tags.insert(L"Release#22H2"); From 69969124913e2d0acd1b82e6784e4c4c281c9374 Mon Sep 17 00:00:00 2001 From: fabienfl Date: Tue, 4 Jun 2024 13:04:02 +0200 Subject: [PATCH 56/60] OrcCommand: NtfsInfo: fix volstat incomplete output for vss --- .../Command/NTFSInfo/NTFSInfo_Run.cpp | 23 +++++++++++++++---- 1 file changed, 19 insertions(+), 4 deletions(-) diff --git a/src/OrcCommand/Command/NTFSInfo/NTFSInfo_Run.cpp b/src/OrcCommand/Command/NTFSInfo/NTFSInfo_Run.cpp index f0152c03..ea0cc297 100644 --- a/src/OrcCommand/Command/NTFSInfo/NTFSInfo_Run.cpp +++ b/src/OrcCommand/Command/NTFSInfo/NTFSInfo_Run.cpp @@ -695,20 +695,36 @@ HRESULT Main::WriteVolStats( outputPaths = it->second; } - auto reader = loc->GetReader(); + auto ntfsReader = loc->GetReader(); - if (reader == nullptr) + if (ntfsReader == nullptr) { return E_FAIL; } + if (ntfsReader->VolumeSerialNumber() == 0) + { + int debug = 0; + } + + std::shared_ptr reader; + auto shadow = loc->GetShadow(); + if (shadow && shadow->parentVolume) + { + reader = shadow->parentVolume; + } + else + { + reader = ntfsReader; + } + SystemDetails::WriteComputerName(volStatOutput); volStatOutput.WriteInteger(reader->VolumeSerialNumber()); volStatOutput.WriteString(reader->GetLocation()); volStatOutput.WriteString(FSVBR::GetFSName(reader->GetFSType()).c_str()); volStatOutput.WriteBool(loc->GetParse()); volStatOutput.WriteString(fmt::format(L"{}", fmt::join(loc->GetPaths(), L";"))); - volStatOutput.WriteString(loc->GetShadow() ? ToStringW(loc->GetShadow()->guid).c_str() : L""); + volStatOutput.WriteString(shadow ? ToStringW(shadow->guid).c_str() : L"{00000000-0000-0000-0000-000000000000}"); if (!outputPaths) { @@ -823,7 +839,6 @@ HRESULT Main::RunThroughMFT() Log::Error("Failed to create writers for NTFSInfo [{}]", SystemError(hr)); return hr; } - } auto fileinfoIterator = begin(m_FileInfoOutput.Outputs()); From 12f62bc33cafd15077a57fa6ffcb2c1126ce6489 Mon Sep 17 00:00:00 2001 From: fabienfl Date: Tue, 12 Sep 2023 16:20:21 +0200 Subject: [PATCH 57/60] OrcLib: Filesystem: add FileAttribute --- src/OrcLib/CMakeLists.txt | 2 + src/OrcLib/Filesystem/FileAttribute.cpp | 226 ++++++++++++++++++++++++ src/OrcLib/Filesystem/FileAttribute.h | 85 +++++++++ 3 files changed, 313 insertions(+) create mode 100644 src/OrcLib/Filesystem/FileAttribute.cpp create mode 100644 src/OrcLib/Filesystem/FileAttribute.h diff --git a/src/OrcLib/CMakeLists.txt b/src/OrcLib/CMakeLists.txt index f5ab79a6..5e14531c 100644 --- a/src/OrcLib/CMakeLists.txt +++ b/src/OrcLib/CMakeLists.txt @@ -553,6 +553,8 @@ source_group(In&Out\\TableOutput\\ApacheOrc ) set(SRC_FILESYSTEM + "Filesystem/FileAttribute.h" + "Filesystem/FileAttribute.cpp" "Filesystem/Ntfs/Attribute/ReparsePoint/WofReparsePoint.h" "Filesystem/Ntfs/Attribute/ReparsePoint/WofReparsePoint.cpp" "Filesystem/Ntfs/Compression/WofChunks.h" diff --git a/src/OrcLib/Filesystem/FileAttribute.cpp b/src/OrcLib/Filesystem/FileAttribute.cpp new file mode 100644 index 00000000..55008693 --- /dev/null +++ b/src/OrcLib/Filesystem/FileAttribute.cpp @@ -0,0 +1,226 @@ +// +// SPDX-License-Identifier: LGPL-2.1-or-later +// +// Copyright © 2023 ANSSI. All Rights Reserved. +// +// Author(s): fabienfl (ANSSI) +// +#include "FileAttribute.h" + +#include +#include + +#include "Log/Log.h" +#include "Utils/String.h" + +using namespace Orc; + +namespace { + +constexpr std::string_view kUnknown = ""; +constexpr std::string_view kNone = ""; + +constexpr std::string_view kFileAttributeReadOnly = "FILE_ATTRIBUTE_READONLY"; +constexpr std::string_view kFileAttributeHidden = "FILE_ATTRIBUTE_HIDDEN"; +constexpr std::string_view kFileAttributeSystem = "FILE_ATTRIBUTE_SYSTEM"; +constexpr std::string_view kFileAttributeDirectory = "FILE_ATTRIBUTE_DIRECTORY"; +constexpr std::string_view kFileAttributeArchive = "FILE_ATTRIBUTE_ARCHIVE"; +constexpr std::string_view kFileAttributeDevice = "FILE_ATTRIBUTE_DEVICE"; +constexpr std::string_view kFileAttributeNormal = "FILE_ATTRIBUTE_NORMAL"; +constexpr std::string_view kFileAttributeTemporary = "FILE_ATTRIBUTE_TEMPORARY"; +constexpr std::string_view kFileAttributeSparseFile = "FILE_ATTRIBUTE_SPARSE_FILE"; +constexpr std::string_view kFileAttributeReparsePoint = "FILE_ATTRIBUTE_REPARSE_POINT"; +constexpr std::string_view kFileAttributeCompressed = "FILE_ATTRIBUTE_COMPRESSED"; +constexpr std::string_view kFileAttributeOffline = "FILE_ATTRIBUTE_OFFLINE"; +constexpr std::string_view kFileAttributeNotContentIndexed = "FILE_ATTRIBUTE_NOT_CONTENT_INDEXED"; +constexpr std::string_view kFileAttributeEncrypted = "FILE_ATTRIBUTE_ENCRYPTED"; +constexpr std::string_view kFileAttributeIntegrityStream = "FILE_ATTRIBUTE_INTEGRITY_STREAM"; +constexpr std::string_view kFileAttributeVirtual = "FILE_ATTRIBUTE_VIRTUAL"; +constexpr std::string_view kFileAttributeNoScrubData = "FILE_ATTRIBUTE_NO_SCRUB_DATA"; +constexpr std::string_view kFileAttributeEA = "FILE_ATTRIBUTE_EA"; +constexpr std::string_view kFileAttributePinned = "FILE_ATTRIBUTE_PINNED"; +constexpr std::string_view kFileAttributeUnpinned = "FILE_ATTRIBUTE_UNPINNED"; +constexpr std::string_view kFileAttributeRecallOnOpen = "FILE_ATTRIBUTE_RECALL_ON_OPEN"; +constexpr std::string_view kFileAttributeRecallOnDataAccess = "FILE_ATTRIBUTE_RECALL_ON_DATA_ACCESS"; + +constexpr std::array kFileAttributes = { + std::tuple {FileAttribute::kFileAttributeReadOnly, kFileAttributeReadOnly, 'R'}, + std::tuple {FileAttribute::kFileAttributeHidden, kFileAttributeHidden, 'H'}, + std::tuple {FileAttribute::kFileAttributeSystem, kFileAttributeSystem, 'S'}, + std::tuple {FileAttribute::kFileAttributeDirectory, kFileAttributeDirectory, 'D'}, + std::tuple {FileAttribute::kFileAttributeArchive, kFileAttributeArchive, 'A'}, + std::tuple {FileAttribute::kFileAttributeDevice, kFileAttributeDevice, 'd'}, + std::tuple {FileAttribute::kFileAttributeNormal, kFileAttributeNormal, 'N'}, + std::tuple {FileAttribute::kFileAttributeTemporary, kFileAttributeTemporary, 'T'}, + std::tuple {FileAttribute::kFileAttributeSparseFile, kFileAttributeSparseFile, 'P'}, + std::tuple {FileAttribute::kFileAttributeReparsePoint, kFileAttributeReparsePoint, 'L'}, + std::tuple {FileAttribute::kFileAttributeCompressed, kFileAttributeCompressed, 'C'}, + std::tuple {FileAttribute::kFileAttributeOffline, kFileAttributeOffline, 'O'}, + std::tuple {FileAttribute::kFileAttributeNotContentIndexed, kFileAttributeNotContentIndexed, 'I'}, + std::tuple {FileAttribute::kFileAttributeEncrypted, kFileAttributeEncrypted, 'E'}, + std::tuple {FileAttribute::kFileAttributeIntegrityStream, kFileAttributeIntegrityStream, 's'}, + std::tuple {FileAttribute::kFileAttributeVirtual, kFileAttributeVirtual, 'V'}, + std::tuple {FileAttribute::kFileAttributeNoScrubData, kFileAttributeNoScrubData, 'B'}, + std::tuple {FileAttribute::kFileAttributeEA, kFileAttributeEA, 'e'}, + std::tuple {FileAttribute::kFileAttributePinned, kFileAttributePinned, 'p'}, + std::tuple {FileAttribute::kFileAttributeUnpinned, kFileAttributeUnpinned, 'u'}, + std::tuple {FileAttribute::kFileAttributeRecallOnOpen, kFileAttributeRecallOnOpen, 'o'}, + std::tuple {FileAttribute::kFileAttributeRecallOnDataAccess, kFileAttributeRecallOnDataAccess, 'a'}, +}; + +bool HasInvalidFlag(uint32_t flags) +{ + using namespace Orc; + + auto remainingFlags = flags; + for (const auto& [flag, string, identifier] : kFileAttributes) + { + if (HasFlag(static_cast(flags), flag)) + { + remainingFlags -= static_cast>(flag); + } + } + + if (remainingFlags) + { + return true; + } + + return false; +} + +} // namespace + +namespace Orc { + +std::string ToString(FileAttribute flags) +{ + if (flags == static_cast(0)) + { + return std::string(kNone); + } + + if (::HasInvalidFlag(std::underlying_type_t(flags))) + { + Log::Debug( + "Failed to convert some FileAttribute flags to string (value: {})", + std::underlying_type_t(flags)); + + return fmt::format("{:#x}", std::underlying_type_t(flags)); + } + + std::vector strings; + for (const auto& [flag, string, identifier] : kFileAttributes) + { + if (HasFlag(flags, flag)) + { + strings.push_back(string); + } + } + + std::string output; + Join(std::cbegin(strings), std::cend(strings), std::back_inserter(output), '|'); + return output; +} + +std::wstring ToStringW(FileAttribute flags) +{ + auto s = ToString(flags); + + std::wstring output; + std::copy(std::cbegin(s), std::cend(s), std::back_inserter(output)); + return output; +} + +char ToIdentifier(FileAttribute flags) +{ + if (flags == static_cast(0)) + { + return '?'; + } + + if (::HasInvalidFlag(std::underlying_type_t(flags))) + { + Log::Debug( + "Failed to convert some FileAttribute flags to identifier (value: {})", + std::underlying_type_t(flags)); + + return '?'; + } + + for (const auto& [f, s, identifier] : kFileAttributes) + { + if (HasFlag(flags, f)) + { + if (flags != f) + { + Log::Debug( + "Failed to convert some FileAttribute flags to unique identifier (value: {})", + std::underlying_type_t(flags)); + return '?'; + } + + return identifier; + } + } + + return '?'; +} + +wchar_t ToIdentifierW(FileAttribute flags) +{ + return ToIdentifier(flags); +} + +std::string ToIdentifiers(FileAttribute flags) +{ + if (flags == static_cast(0)) + { + return std::string(kNone); + } + + if (::HasInvalidFlag(std::underlying_type_t(flags))) + { + Log::Debug( + "Failed to convert some FileAttribute flags to string (value: {})", + std::underlying_type_t(flags)); + + return fmt::format("{:#x}", std::underlying_type_t(flags)); + } + + std::string output; + for (const auto& [flag, s, identifier] : kFileAttributes) + { + if (HasFlag(flags, flag)) + { + output.push_back(identifier); + } + else + { + output.push_back('.'); + } + } + + return output; +} + +std::wstring ToIdentifiersW(FileAttribute flags) +{ + auto s = ToIdentifiers(flags); + + std::wstring output; + std::copy(std::cbegin(s), std::cend(s), std::back_inserter(output)); + return output; +} + +FileAttribute ToFileAttribute(const uint32_t attributes, std::error_code& ec) +{ + if (::HasInvalidFlag(std::underlying_type_t(attributes))) + { + ec = std::make_error_code(std::errc::invalid_argument); + } + + return static_cast(attributes); +} + +} // namespace Orc diff --git a/src/OrcLib/Filesystem/FileAttribute.h b/src/OrcLib/Filesystem/FileAttribute.h new file mode 100644 index 00000000..cfe0cfcf --- /dev/null +++ b/src/OrcLib/Filesystem/FileAttribute.h @@ -0,0 +1,85 @@ +// +// SPDX-License-Identifier: LGPL-2.1-or-later +// +// Copyright © 2023 ANSSI. All Rights Reserved. +// +// Author(s): fabienfl (ANSSI) +// + +#include "Utils/EnumFlags.h" + +namespace Orc { + +// From 'winnt.h' +#define ORC_FILE_ATTRIBUTE_READONLY 0x00000001 +#define ORC_FILE_ATTRIBUTE_HIDDEN 0x00000002 +#define ORC_FILE_ATTRIBUTE_SYSTEM 0x00000004 +#define ORC_FILE_ATTRIBUTE_DIRECTORY 0x00000010 +#define ORC_FILE_ATTRIBUTE_ARCHIVE 0x00000020 +#define ORC_FILE_ATTRIBUTE_DEVICE 0x00000040 +#define ORC_FILE_ATTRIBUTE_NORMAL 0x00000080 +#define ORC_FILE_ATTRIBUTE_TEMPORARY 0x00000100 +#define ORC_FILE_ATTRIBUTE_SPARSE_FILE 0x00000200 +#define ORC_FILE_ATTRIBUTE_REPARSE_POINT 0x00000400 +#define ORC_FILE_ATTRIBUTE_COMPRESSED 0x00000800 +#define ORC_FILE_ATTRIBUTE_OFFLINE 0x00001000 +#define ORC_FILE_ATTRIBUTE_NOT_CONTENT_INDEXED 0x00002000 +#define ORC_FILE_ATTRIBUTE_ENCRYPTED 0x00004000 +#define ORC_FILE_ATTRIBUTE_INTEGRITY_STREAM 0x00008000 +#define ORC_FILE_ATTRIBUTE_VIRTUAL 0x00010000 +#define ORC_FILE_ATTRIBUTE_NO_SCRUB_DATA 0x00020000 +#define ORC_FILE_ATTRIBUTE_EA 0x00040000 +#define ORC_FILE_ATTRIBUTE_PINNED 0x00080000 +#define ORC_FILE_ATTRIBUTE_UNPINNED 0x00100000 +#define ORC_FILE_ATTRIBUTE_RECALL_ON_OPEN 0x00040000 +#define ORC_FILE_ATTRIBUTE_RECALL_ON_DATA_ACCESS 0x00400000 + +enum class FileAttribute +{ + kFileAttributeReadOnly = ORC_FILE_ATTRIBUTE_READONLY, + kFileAttributeHidden = ORC_FILE_ATTRIBUTE_HIDDEN, + kFileAttributeSystem = ORC_FILE_ATTRIBUTE_SYSTEM, + kFileAttributeDirectory = ORC_FILE_ATTRIBUTE_DIRECTORY, + kFileAttributeArchive = ORC_FILE_ATTRIBUTE_ARCHIVE, + kFileAttributeDevice = ORC_FILE_ATTRIBUTE_DEVICE, + kFileAttributeNormal = ORC_FILE_ATTRIBUTE_NORMAL, + kFileAttributeTemporary = ORC_FILE_ATTRIBUTE_TEMPORARY, + kFileAttributeSparseFile = ORC_FILE_ATTRIBUTE_SPARSE_FILE, + kFileAttributeReparsePoint = ORC_FILE_ATTRIBUTE_REPARSE_POINT, + kFileAttributeCompressed = ORC_FILE_ATTRIBUTE_COMPRESSED, + kFileAttributeOffline = ORC_FILE_ATTRIBUTE_OFFLINE, + kFileAttributeNotContentIndexed = ORC_FILE_ATTRIBUTE_NOT_CONTENT_INDEXED, + kFileAttributeEncrypted = ORC_FILE_ATTRIBUTE_ENCRYPTED, + kFileAttributeIntegrityStream = ORC_FILE_ATTRIBUTE_INTEGRITY_STREAM, + kFileAttributeVirtual = ORC_FILE_ATTRIBUTE_VIRTUAL, + kFileAttributeNoScrubData = ORC_FILE_ATTRIBUTE_NO_SCRUB_DATA, + kFileAttributeEA = ORC_FILE_ATTRIBUTE_EA, + kFileAttributePinned = ORC_FILE_ATTRIBUTE_PINNED, + kFileAttributeUnpinned = ORC_FILE_ATTRIBUTE_UNPINNED, + kFileAttributeRecallOnOpen = ORC_FILE_ATTRIBUTE_RECALL_ON_OPEN, + kFileAttributeRecallOnDataAccess = ORC_FILE_ATTRIBUTE_RECALL_ON_DATA_ACCESS +}; + +ENABLE_BITMASK_OPERATORS(FileAttribute) + +// Example: 0x880 => FILE_ATTRIBUTE_NORMAL|FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM +std::string ToString(FileAttribute attributes); + +// Example: 0x880 => FILE_ATTRIBUTE_NORMAL|FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM +std::wstring ToStringW(FileAttribute attributes); + +// Example: 0x880 => ....HN....S........... +std::string ToIdentifiers(FileAttribute attributes); + +// Example: 0x880 => ....HN....S........... +std::wstring ToIdentifiersW(FileAttribute attributes); + +// Example: 0x80 => N +char ToIdentifier(FileAttribute flags); + +// Example: 0x80 => N +wchar_t ToIdentifierW(FileAttribute flags); + +FileAttribute ToFileAttribute(const uint32_t attributes, std::error_code& ec); + +} // namespace Orc From 18475b953a6a0f47929941f05559eb4d25c8f27d Mon Sep 17 00:00:00 2001 From: fabienfl Date: Tue, 12 Sep 2023 16:24:06 +0200 Subject: [PATCH 58/60] OrcLib: use FileAttribute's ToIdentifiers to refactor --- src/OrcLib/BoundTableRecord.cpp | 35 ++------------------- src/OrcLib/CsvFileWriter.cpp | 18 ++--------- src/OrcLib/StructuredOutputWriter.cpp | 19 ++--------- src/OrcLib/Text/Print/Ntfs/MFTRecord.cpp | 19 ++--------- tests/OrcLibTest/structured_output_test.cpp | 8 ++--- 5 files changed, 16 insertions(+), 83 deletions(-) diff --git a/src/OrcLib/BoundTableRecord.cpp b/src/OrcLib/BoundTableRecord.cpp index e256ae72..9080a517 100644 --- a/src/OrcLib/BoundTableRecord.cpp +++ b/src/OrcLib/BoundTableRecord.cpp @@ -13,6 +13,7 @@ #include "WideAnsi.h" #include +#include "Filesystem/FileAttribute.h" using namespace Orc; using namespace Orc::TableOutput; @@ -333,43 +334,13 @@ HRESULT BoundColumn::WriteAttributes(DWORD dwAttributes) boundData.Dword = dwAttributes; break; case UTF16Type: - if (FAILED( - hr = PrintToBuffer( - L"%c%c%c%c%c%c%c%c%c%c%c%c%c", - dwAttributes & FILE_ATTRIBUTE_ARCHIVE ? L'A' : L'.', - dwAttributes & FILE_ATTRIBUTE_COMPRESSED ? L'C' : L'.', - dwAttributes & FILE_ATTRIBUTE_DIRECTORY ? L'D' : L'.', - dwAttributes & FILE_ATTRIBUTE_ENCRYPTED ? L'E' : L'.', - dwAttributes & FILE_ATTRIBUTE_HIDDEN ? L'H' : L'.', - dwAttributes & FILE_ATTRIBUTE_NORMAL ? L'N' : L'.', - dwAttributes & FILE_ATTRIBUTE_OFFLINE ? L'O' : L'.', - dwAttributes & FILE_ATTRIBUTE_READONLY ? L'R' : L'.', - dwAttributes & FILE_ATTRIBUTE_REPARSE_POINT ? L'L' : L'.', - dwAttributes & FILE_ATTRIBUTE_SPARSE_FILE ? L'P' : L'.', - dwAttributes & FILE_ATTRIBUTE_SYSTEM ? L'S' : L'.', - dwAttributes & FILE_ATTRIBUTE_TEMPORARY ? L'T' : L'.', - dwAttributes & FILE_ATTRIBUTE_VIRTUAL ? L'V' : L'.'))) + if (FAILED(hr = PrintToBuffer(ToIdentifiersW(static_cast(dwAttributes)).c_str()))) { return hr; } break; case UTF8Type: - if (FAILED( - hr = PrintToBuffer( - "%c%c%c%c%c%c%c%c%c%c%c%c%c", - dwAttributes & FILE_ATTRIBUTE_ARCHIVE ? 'A' : '.', - dwAttributes & FILE_ATTRIBUTE_COMPRESSED ? 'C' : '.', - dwAttributes & FILE_ATTRIBUTE_DIRECTORY ? 'D' : '.', - dwAttributes & FILE_ATTRIBUTE_ENCRYPTED ? 'E' : '.', - dwAttributes & FILE_ATTRIBUTE_HIDDEN ? 'H' : '.', - dwAttributes & FILE_ATTRIBUTE_NORMAL ? 'N' : '.', - dwAttributes & FILE_ATTRIBUTE_OFFLINE ? 'O' : '.', - dwAttributes & FILE_ATTRIBUTE_READONLY ? 'R' : '.', - dwAttributes & FILE_ATTRIBUTE_REPARSE_POINT ? 'L' : '.', - dwAttributes & FILE_ATTRIBUTE_SPARSE_FILE ? 'P' : '.', - dwAttributes & FILE_ATTRIBUTE_SYSTEM ? 'S' : '.', - dwAttributes & FILE_ATTRIBUTE_TEMPORARY ? 'T' : '.', - dwAttributes & FILE_ATTRIBUTE_VIRTUAL ? 'V' : '.'))) + if (FAILED(hr = PrintToBuffer(ToIdentifiers(static_cast(dwAttributes)).c_str()))) { return hr; } diff --git a/src/OrcLib/CsvFileWriter.cpp b/src/OrcLib/CsvFileWriter.cpp index 33d604d0..03ed3a55 100644 --- a/src/OrcLib/CsvFileWriter.cpp +++ b/src/OrcLib/CsvFileWriter.cpp @@ -29,6 +29,8 @@ #include "Log/Log.h" +#include "Filesystem/FileAttribute.h" + using namespace Orc; namespace fs = std::filesystem; @@ -436,21 +438,7 @@ HRESULT Orc::TableOutput::CSV::Writer::WriteFormated_(std::string_view szFormat, STDMETHODIMP Orc::TableOutput::CSV::Writer::WriteAttributes(DWORD dwFileAttributes) { - if (auto hr = WriteFormated( - L"{}{}{}{}{}{}{}{}{}{}{}{}{}", - dwFileAttributes & FILE_ATTRIBUTE_ARCHIVE ? L'A' : L'.', - dwFileAttributes & FILE_ATTRIBUTE_COMPRESSED ? L'C' : L'.', - dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY ? L'D' : L'.', - dwFileAttributes & FILE_ATTRIBUTE_ENCRYPTED ? L'E' : L'.', - dwFileAttributes & FILE_ATTRIBUTE_HIDDEN ? L'H' : L'.', - dwFileAttributes & FILE_ATTRIBUTE_NORMAL ? L'N' : L'.', - dwFileAttributes & FILE_ATTRIBUTE_OFFLINE ? L'O' : L'.', - dwFileAttributes & FILE_ATTRIBUTE_READONLY ? L'R' : L'.', - dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT ? L'L' : L'.', - dwFileAttributes & FILE_ATTRIBUTE_SPARSE_FILE ? L'P' : L'.', - dwFileAttributes & FILE_ATTRIBUTE_SYSTEM ? L'S' : L'.', - dwFileAttributes & FILE_ATTRIBUTE_TEMPORARY ? L'T' : L'.', - dwFileAttributes & FILE_ATTRIBUTE_VIRTUAL ? L'V' : L'.'); + if (auto hr = WriteFormated(ToIdentifiersW(static_cast(dwFileAttributes))); FAILED(hr)) { AbandonColumn(); diff --git a/src/OrcLib/StructuredOutputWriter.cpp b/src/OrcLib/StructuredOutputWriter.cpp index 8f1eef32..f01ea857 100644 --- a/src/OrcLib/StructuredOutputWriter.cpp +++ b/src/OrcLib/StructuredOutputWriter.cpp @@ -13,6 +13,7 @@ #include "OutputSpec.h" #include "FileStream.h" #include "BinaryBuffer.h" +#include "Filesystem/FileAttribute.h" using namespace std::string_view_literals; using namespace Orc; @@ -53,22 +54,8 @@ HRESULT Orc::StructuredOutput::Writer::WriteBuffer(_Buffer& buffer, LARGE_INTEGE HRESULT Orc::StructuredOutput::Writer::WriteAttributesBuffer(_Buffer& buffer, DWORD dwFileAttributes) { - fmt::format_to( - std::back_inserter(buffer), - L"{}{}{}{}{}{}{}{}{}{}{}{}{}", - dwFileAttributes & FILE_ATTRIBUTE_ARCHIVE ? L'A' : L'.', - dwFileAttributes & FILE_ATTRIBUTE_COMPRESSED ? L'C' : L'.', - dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY ? L'D' : L'.', - dwFileAttributes & FILE_ATTRIBUTE_ENCRYPTED ? L'E' : L'.', - dwFileAttributes & FILE_ATTRIBUTE_HIDDEN ? L'H' : L'.', - dwFileAttributes & FILE_ATTRIBUTE_NORMAL ? L'N' : L'.', - dwFileAttributes & FILE_ATTRIBUTE_OFFLINE ? L'O' : L'.', - dwFileAttributes & FILE_ATTRIBUTE_READONLY ? L'R' : L'.', - dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT ? L'L' : L'.', - dwFileAttributes & FILE_ATTRIBUTE_SPARSE_FILE ? L'P' : L'.', - dwFileAttributes & FILE_ATTRIBUTE_SYSTEM ? L'S' : L'.', - dwFileAttributes & FILE_ATTRIBUTE_TEMPORARY ? L'T' : L'.', - dwFileAttributes & FILE_ATTRIBUTE_VIRTUAL ? L'V' : L'.'); + const auto s = ToIdentifiersW(static_cast(dwFileAttributes)); + std::copy(std::cbegin(s), std::cend(s), std::back_inserter(buffer)); return S_OK; } diff --git a/src/OrcLib/Text/Print/Ntfs/MFTRecord.cpp b/src/OrcLib/Text/Print/Ntfs/MFTRecord.cpp index b9eff2de..4d43b994 100644 --- a/src/OrcLib/Text/Print/Ntfs/MFTRecord.cpp +++ b/src/OrcLib/Text/Print/Ntfs/MFTRecord.cpp @@ -28,6 +28,8 @@ #include "Text/Fmt/Offset.h" #include "Text/Fmt/FILETIME.h" +#include "Filesystem/FileAttribute.h" + namespace Orc { namespace Text { @@ -133,22 +135,7 @@ Orc::Result AttributeTypeToString(ATTRIBUTE_TYPE_CODE code) void PrintValueFileAttributes(Orc::Text::Tree& root, const std::wstring& name, ULONG fileAttributes) { - const auto attributes = fmt::format( - L"{}{}{}{}{}{}{}{}{}{}{}{}{}", - fileAttributes & FILE_ATTRIBUTE_ARCHIVE ? L'A' : L'.', - fileAttributes & FILE_ATTRIBUTE_COMPRESSED ? L'C' : L'.', - fileAttributes & FILE_ATTRIBUTE_DIRECTORY ? L'D' : L'.', - fileAttributes & FILE_ATTRIBUTE_ENCRYPTED ? L'E' : L'.', - fileAttributes & FILE_ATTRIBUTE_HIDDEN ? L'H' : L'.', - fileAttributes & FILE_ATTRIBUTE_NORMAL ? L'N' : L'.', - fileAttributes & FILE_ATTRIBUTE_OFFLINE ? L'O' : L'.', - fileAttributes & FILE_ATTRIBUTE_READONLY ? L'R' : L'.', - fileAttributes & FILE_ATTRIBUTE_REPARSE_POINT ? L'L' : L'.', - fileAttributes & FILE_ATTRIBUTE_SPARSE_FILE ? L'P' : L'.', - fileAttributes & FILE_ATTRIBUTE_SYSTEM ? L'S' : L'.', - fileAttributes & FILE_ATTRIBUTE_TEMPORARY ? L'T' : L'.', - fileAttributes & FILE_ATTRIBUTE_VIRTUAL ? L'V' : L'.'); - + const auto attributes = ToIdentifiersW(static_cast(fileAttributes)); PrintValue(root, name, attributes); } diff --git a/tests/OrcLibTest/structured_output_test.cpp b/tests/OrcLibTest/structured_output_test.cpp index f67fdeed..33753162 100644 --- a/tests/OrcLibTest/structured_output_test.cpp +++ b/tests/OrcLibTest/structured_output_test.cpp @@ -324,7 +324,7 @@ TEST_CLASS(StructuredOutputTest) auto writer = StructuredOutputWriter::GetWriter(result_stream, OutputSpec::Kind::XML, std::move(options)); Assert::IsTrue(SUCCEEDED(WriterSingleTest(writer))); - Assert::IsTrue(SUCCEEDED(CompareTestResult(result_stream, L"3038DD6F8A0B50BF69E193ABBA94183212763A4B"))); + Assert::IsTrue(SUCCEEDED(CompareTestResult(result_stream, L"A8B673BC51F644F5D5DE69B66137F72C0142BA02"))); writer.reset(); @@ -336,7 +336,7 @@ TEST_CLASS(StructuredOutputTest) writer = StructuredOutputWriter::GetWriter(result_stream, OutputSpec::Kind::XML, std::move(options)); Assert::IsTrue(SUCCEEDED(WriterSingleTest(writer))); - Assert::IsTrue(SUCCEEDED(CompareTestResult(result_stream, L"0632A91DC98CBF17428082C12F759AD98D951AAF"))); + Assert::IsTrue(SUCCEEDED(CompareTestResult(result_stream, L"6D5F96BB45D8A64AD2F4BE2D5F638887A14FA0D3"))); } TEST_METHOD(RobustStructuredOutputTest) @@ -357,7 +357,7 @@ TEST_CLASS(StructuredOutputTest) std::make_shared(std::dynamic_pointer_cast(writer)); Assert::IsTrue(SUCCEEDED(WriterSingleTest(robust_writer))); - Assert::IsTrue(SUCCEEDED(CompareTestResult(result_stream, L"3038DD6F8A0B50BF69E193ABBA94183212763A4B"))); + Assert::IsTrue(SUCCEEDED(CompareTestResult(result_stream, L"A8B673BC51F644F5D5DE69B66137F72C0142BA02"))); robust_writer.reset(); @@ -372,7 +372,7 @@ TEST_CLASS(StructuredOutputTest) std::make_shared(std::dynamic_pointer_cast(writer)); Assert::IsTrue(SUCCEEDED(WriterSingleTest(robust_writer))); - Assert::IsTrue(SUCCEEDED(CompareTestResult(result_stream, L"0632A91DC98CBF17428082C12F759AD98D951AAF"))); + Assert::IsTrue(SUCCEEDED(CompareTestResult(result_stream, L"6D5F96BB45D8A64AD2F4BE2D5F638887A14FA0D3"))); } HRESULT WriteGargabeElementTest(const std::shared_ptr& stream, WCHAR wGarbageCode) From 7771bdc1016e6af4d93cf3017f98504263318757 Mon Sep 17 00:00:00 2001 From: fabienfl Date: Mon, 10 Jun 2024 17:45:45 +0200 Subject: [PATCH 59/60] OrcLib: BITSAgent: add option to delete smb share after upload Use upload attribute 'delete_smb_share="true"' This will close the connection and a linux smb server will be able to free the associated context. --- src/OrcLib/BITSAgent.cpp | 24 +++++++++++++++++++ .../Configuration/ConfigFile_Common.cpp | 4 ++++ src/OrcLib/Configuration/ConfigItem.h | 1 + src/OrcLib/OutputSpec.cpp | 13 ++++++++++ src/OrcLib/OutputSpec.h | 7 +++++- 5 files changed, 48 insertions(+), 1 deletion(-) diff --git a/src/OrcLib/BITSAgent.cpp b/src/OrcLib/BITSAgent.cpp index f92f6a57..9ee35508 100644 --- a/src/OrcLib/BITSAgent.cpp +++ b/src/OrcLib/BITSAgent.cpp @@ -13,6 +13,7 @@ #include #include #include +#include #include "BITSAgent.h" #include "ParameterCheck.h" @@ -309,6 +310,29 @@ BITSAgent::UploadFile( } } + if (m_config.bitsMode == OutputSpec::BITSMode::SMB && m_config.bitsDeleteSmbShare.has_value() + && *m_config.bitsDeleteSmbShare == true) + { + Log::Debug(L"Configure NotifyCmd to delete share: {}{}", m_config.ServerName, m_config.RootPath); + + constexpr std::wstring_view forbidden(L";&|()<>*?\""); + if (boost::algorithm::contains(m_config.ServerName, forbidden) + || boost::algorithm::contains(m_config.RootPath, forbidden)) + { + Log::Warn("Invalid characters in server name or network path"); + } + else + { + if (!cmdLine.str().empty()) + { + cmdLine << L" & "; + } + + cmdLine << L"net use /del \"\\\\" << m_config.ServerName << m_config.RootPath << L"\""; + + } + } + if (FAILED(hr = job2->SetNotifyCmdLine(strCmdSpec.c_str(), cmdLine.str().c_str()))) { Log::Error(L"Failed to SetNotifyCmdLine to delete uploaded files [{}]", SystemError(hr)); diff --git a/src/OrcLib/Configuration/ConfigFile_Common.cpp b/src/OrcLib/Configuration/ConfigFile_Common.cpp index ca444cbc..526fc28a 100644 --- a/src/OrcLib/Configuration/ConfigFile_Common.cpp +++ b/src/OrcLib/Configuration/ConfigFile_Common.cpp @@ -106,6 +106,10 @@ HRESULT Orc::Config::Common::upload(ConfigItem& parent, DWORD dwIndex, std::wstr return hr; if (FAILED(hr = parent.SubItems[dwIndex].AddAttribute(L"uri", CONFIG_UPLOAD_URI, ConfigItem::OPTION))) return hr; + if (FAILED( + hr = parent.SubItems[dwIndex].AddAttribute( + L"delete_smb_share", CONFIG_UPLOAD_BITS_SMB_DELETE_SHARE, ConfigItem::OPTION))) + return hr; return S_OK; } diff --git a/src/OrcLib/Configuration/ConfigItem.h b/src/OrcLib/Configuration/ConfigItem.h index b1706b13..3c22cdea 100644 --- a/src/OrcLib/Configuration/ConfigItem.h +++ b/src/OrcLib/Configuration/ConfigItem.h @@ -202,6 +202,7 @@ constexpr auto CONFIG_UPLOAD_AUTHSCHEME = 8U; constexpr auto CONFIG_UPLOAD_FILTER_EXC = 9U; constexpr auto CONFIG_UPLOAD_FILTER_INC = 10U; constexpr auto CONFIG_UPLOAD_URI = 11U; +constexpr auto CONFIG_UPLOAD_BITS_SMB_DELETE_SHARE = 12U; // DOWNLOAD constexpr auto CONFIG_DOWNLOAD_METHOD = 0U; diff --git a/src/OrcLib/OutputSpec.cpp b/src/OrcLib/OutputSpec.cpp index 74f5a769..ba9e7637 100644 --- a/src/OrcLib/OutputSpec.cpp +++ b/src/OrcLib/OutputSpec.cpp @@ -565,6 +565,19 @@ HRESULT OutputSpec::Upload::Configure(const ConfigItem& item) } } + if (::HasValue(item, CONFIG_UPLOAD_BITS_SMB_DELETE_SHARE)) + { + if (bitsMode != BITSMode::SMB) + { + Log::Warn(L"Option 'delete_smb_share' is only supported with BITS SMB mode"); + } + else + { + const auto str = item.SubItems[CONFIG_UPLOAD_BITS_SMB_DELETE_SHARE].c_str(); + bitsDeleteSmbShare = boost::iequals(str, L"true") || boost::iequals(str, L"yes"); + } + } + if (::HasValue(item, CONFIG_UPLOAD_FILTER_INC)) { boost::split( diff --git a/src/OrcLib/OutputSpec.h b/src/OrcLib/OutputSpec.h index 25ce093e..4e6ea499 100644 --- a/src/OrcLib/OutputSpec.h +++ b/src/OrcLib/OutputSpec.h @@ -54,12 +54,17 @@ class OutputSpec std::wstring Password; std::wstring JobName; + std::optional bitsDeleteSmbShare; + std::vector FilterInclude; std::vector FilterExclude; Upload() : Method(UploadMethod::NoUpload) - , Operation(UploadOperation::NoOp) {}; + , Operation(UploadOperation::NoOp) + , bitsDeleteSmbShare(false) + { + } HRESULT Configure(const ConfigItem& item); From 7084bce8016a724e72ca5cfa9511b66a9cb9f9ad Mon Sep 17 00:00:00 2001 From: fabienfl Date: Tue, 4 Jun 2024 09:47:05 +0200 Subject: [PATCH 60/60] changelog: update to 10.2.5 --- CHANGELOG.md | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5846e963..88052e9e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,27 @@ # ChangeLog +## [10.2.5] - 2024-06-07 +### Added +- Outcome: add outcome.system_type (Workstation...) +- Outline: add outline.system_type (Workstation...) +- Outline: add outline.system.hypervisor +- Outline: add system.codepage and codepage_name +- Outline: add command's timeout configuration +- Outline: add command's expected output files +- WolfLauncher: add pattern {RunId} to use within configuration files +- WolfLauncher: BITS: add option 'delete_smb_share' to delete smb share after upload + +### Changed +- Outline: set outline.computer_name with /FullComputer +- Outline: set outline.system[.name|.fullname] with host's name +- Outcome: set outcome.computer_name with /FullComputer +- Outcome: replace status 'running_command' with 'live' + +### Fixed +- WolfLauncher: fix cpu weight configuration +- Ntfsinfo: volstat output + + ## [10.2.4] - 2024-02-02 ### Added - Outline: add install_date, install_time and shutdown_time filled from registry