diff options
Diffstat (limited to 'include/cru/base/platform/win')
| -rw-r--r-- | include/cru/base/platform/win/Base.h | 113 | ||||
| -rw-r--r-- | include/cru/base/platform/win/Stream.h | 66 | ||||
| -rw-r--r-- | include/cru/base/platform/win/StreamConvert.h | 13 | ||||
| -rw-r--r-- | include/cru/base/platform/win/Win32FileStream.h | 42 | ||||
| -rw-r--r-- | include/cru/base/platform/win/Win32SubProcess.h | 41 |
5 files changed, 213 insertions, 62 deletions
diff --git a/include/cru/base/platform/win/Base.h b/include/cru/base/platform/win/Base.h index 83420461..8d221c83 100644 --- a/include/cru/base/platform/win/Base.h +++ b/include/cru/base/platform/win/Base.h @@ -5,6 +5,10 @@ #endif #include "../../Base.h" +#include "../../Bitmask.h" + +#include <optional> +#include <string_view> #define NOMINMAX #define WIN32_LEAN_AND_MEAN @@ -17,8 +21,7 @@ namespace cru::platform::win { class CRU_BASE_API HResultError : public Exception { public: - explicit HResultError(HRESULT h_result); - HResultError(HRESULT h_result, std::string_view message); + explicit HResultError(HRESULT h_result, std::string_view message = ""); HRESULT GetHResult() const { return h_result_; } @@ -26,16 +29,14 @@ class CRU_BASE_API HResultError : public Exception { HRESULT h_result_; }; -inline void ThrowIfFailed(const HRESULT h_result) { - if (FAILED(h_result)) throw HResultError(h_result); -} - -inline void ThrowIfFailed(const HRESULT h_result, std::string_view message) { +inline void CheckHResult(const HRESULT h_result, + std::string_view message = "") { if (FAILED(h_result)) throw HResultError(h_result, message); } class CRU_BASE_API Win32Error : public Exception { public: + Win32Error(); // ::GetLastError is automatically called to get the error code. // The same as Win32Error(::GetLastError(), message) explicit Win32Error(std::string_view message); @@ -46,4 +47,102 @@ class CRU_BASE_API Win32Error : public Exception { private: DWORD error_code_; }; + +inline void CheckWinReturn(BOOL r, std::string_view message = "") { + if (r == FALSE) { + throw Win32Error(message); + } +} + +template <typename H, void (*CloseFunc)(H handle) noexcept> +class CRU_BASE_API TWin32Handle { + public: + TWin32Handle() : handle_(std::nullopt), auto_close_(false) {} + + TWin32Handle(H handle, bool auto_close) + : handle_(handle), auto_close_(auto_close) {} + + CRU_DELETE_COPY(TWin32Handle) + + TWin32Handle(TWin32Handle&& other) noexcept + : handle_(other.handle_), auto_close_(other.auto_close_) { + other.handle_ = std::nullopt; + other.auto_close_ = false; + } + + TWin32Handle& operator=(TWin32Handle&& other) noexcept { + if (this != &other) { + DoClose(); + handle_ = other.handle_; + auto_close_ = other.auto_close_; + other.handle_ = std::nullopt; + other.auto_close_ = false; + } + return *this; + } + + ~TWin32Handle() { DoClose(); } + + public: + bool IsValid() const { return handle_.has_value(); } + + void CheckValid( + std::optional<std::string_view> additional_message = std::nullopt) const { + if (!IsValid()) { + std::string message("The win32 handle is invalid."); + if (additional_message) { + message += " "; + message += *additional_message; + } + throw Exception(std::move(message)); + } + } + + H Get() const { + CheckValid(); + return *handle_; + } + + H Release() { + CheckValid(); + auto handle = *handle_; + handle_ = std::nullopt; + auto_close_ = false; + return handle; + } + + private: + void DoClose() { + if (auto_close_ && handle_) { + CloseFunc(*handle_); + } + } + + private: + std::optional<H> handle_; + bool auto_close_; +}; + +namespace details { +inline void MyCloseHandle(HANDLE handle) noexcept { ::CloseHandle(handle); } +} // namespace details + +using Win32Handle = TWin32Handle<HANDLE, details::MyCloseHandle>; + +struct UniDirectionalWin32PipeResult { + Win32Handle read; + Win32Handle write; +}; + +namespace details { +struct Win32PipeFlagTag; +} +using Win32PipeFlag = Bitmask<details::Win32PipeFlagTag>; +struct Win32PipeFlags { + constexpr static auto ReadInheritable = Win32PipeFlag::FromOffset(1); + constexpr static auto WriteInheritable = Win32PipeFlag::FromOffset(2); +}; + +CRU_BASE_API UniDirectionalWin32PipeResult +OpenUniDirectionalPipe(Win32PipeFlag flag = {}); } // namespace cru::platform::win diff --git a/include/cru/base/platform/win/Stream.h b/include/cru/base/platform/win/Stream.h new file mode 100644 index 00000000..e49bf48b --- /dev/null +++ b/include/cru/base/platform/win/Stream.h @@ -0,0 +1,66 @@ +#pragma once + +#ifndef _WIN32 +#error "This file can only be included on Windows." +#endif + +#include "../../io/Base.h" +#include "../../io/Stream.h" +#include "Base.h" + +#include <objidlbase.h> + +namespace cru::platform::win { +class CRU_BASE_API Win32HandleStream : public io::Stream { + public: + Win32HandleStream(std::string_view path, io::OpenFileFlag flags); + Win32HandleStream(HANDLE handle, bool auto_close, bool can_seek, + bool can_read, bool can_write); + Win32HandleStream(Win32Handle&& handle, bool can_seek, bool can_read, + bool can_write); + ~Win32HandleStream() override; + + protected: + Index DoSeek(Index offset, SeekOrigin origin) override; + Index DoRead(std::byte* buffer, Index offset, Index size) override; + Index DoWrite(const std::byte* buffer, Index offset, Index size) override; + + public: + const Win32Handle& GetHandle() { return handle_; } + + CRU_STREAM_IMPLEMENT_CLOSE_BY_DO_CLOSE + + private: + void DoClose(); + + private: + Win32Handle handle_; +}; + +CRU_BASE_API IStream* ToComStream(io::Stream* stream); + +class CRU_BASE_API ComStream : public io::Stream { + public: + ComStream(std::string_view path, io::OpenFileFlag flags); + ComStream(IStream* com_stream, bool auto_release, bool can_seek, + bool can_read, bool can_write); + ~ComStream() override; + + protected: + Index DoSeek(Index offset, SeekOrigin origin) override; + Index DoRead(std::byte* buffer, Index offset, Index size) override; + Index DoWrite(const std::byte* buffer, Index offset, Index size) override; + + public: + IStream* GetComStream() { return stream_; } + + CRU_STREAM_IMPLEMENT_CLOSE_BY_DO_CLOSE + + private: + void DoClose(); + + private: + IStream* stream_; + bool auto_release_; +}; +} // namespace cru::platform::win diff --git a/include/cru/base/platform/win/StreamConvert.h b/include/cru/base/platform/win/StreamConvert.h deleted file mode 100644 index 085e94e6..00000000 --- a/include/cru/base/platform/win/StreamConvert.h +++ /dev/null @@ -1,13 +0,0 @@ -#pragma once - -#ifndef _WIN32 -#error "This file can only be included on Windows." -#endif - -#include "../../io/Stream.h" - -#include <objidlbase.h> - -namespace cru::platform::win { -CRU_BASE_API IStream* ConvertStreamToComStream(io::Stream* stream); -} diff --git a/include/cru/base/platform/win/Win32FileStream.h b/include/cru/base/platform/win/Win32FileStream.h deleted file mode 100644 index 2980d059..00000000 --- a/include/cru/base/platform/win/Win32FileStream.h +++ /dev/null @@ -1,42 +0,0 @@ -#pragma once - -#ifndef _WIN32 -#error "This file can only be included on Windows." -#endif - -#include "../../io/OpenFileFlag.h" -#include "../../io/Stream.h" - -namespace cru::platform::win { -namespace details { -class Win32FileStreamPrivate; -} - -class CRU_BASE_API Win32FileStream : public io::Stream { - public: - Win32FileStream(std::string path, io::OpenFileFlag flags); - ~Win32FileStream() override; - - protected: - Index DoSeek(Index offset, SeekOrigin origin) override; - Index DoRead(std::byte* buffer, Index offset, Index size) override; - Index DoWrite(const std::byte* buffer, Index offset, Index size) override; - - public: - std::string GetPath() const { return path_; } - io::OpenFileFlag GetOpenFileFlags() const { return flags_; } - - details::Win32FileStreamPrivate* GetPrivate_() { return p_; } - - CRU_STREAM_IMPLEMENT_CLOSE_BY_DO_CLOSE - - private: - void DoClose(); - - private: - std::string path_; - io::OpenFileFlag flags_; - - details::Win32FileStreamPrivate* p_; -}; -} // namespace cru::platform::win diff --git a/include/cru/base/platform/win/Win32SubProcess.h b/include/cru/base/platform/win/Win32SubProcess.h new file mode 100644 index 00000000..e7189b02 --- /dev/null +++ b/include/cru/base/platform/win/Win32SubProcess.h @@ -0,0 +1,41 @@ +#pragma once + +#ifndef _WIN32 +#error "This file can only be included on Windows." +#endif + +#include "../../SubProcess.h" +#include "../../io/AutoReadStream.h" +#include "Base.h" +#include "Stream.h" + +namespace cru::platform::win { +class CRU_BASE_API Win32SubProcessImpl + : public Object, + public virtual IPlatformSubProcessImpl { + CRU_DEFINE_CLASS_LOG_TAG("cru::platform::win::Win32SubProcessImpl") + + public: + explicit Win32SubProcessImpl(); + ~Win32SubProcessImpl(); + + void PlatformCreateProcess(const SubProcessStartInfo& start_info) override; + SubProcessExitResult PlatformWaitForProcess() override; + void PlatformKillProcess() override; + + io::Stream* GetStdinStream() override; + io::Stream* GetStdoutStream() override; + io::Stream* GetStderrStream() override; + + private: + PROCESS_INFORMATION process_; + int exit_code_; + + std::unique_ptr<Win32HandleStream> stdin_stream_; + std::unique_ptr<Win32HandleStream> stdout_stream_; + std::unique_ptr<Win32HandleStream> stderr_stream_; + + std::unique_ptr<io::AutoReadStream> stdout_buffer_stream_; + std::unique_ptr<io::AutoReadStream> stderr_buffer_stream_; +}; +} // namespace cru::platform::win |
