aboutsummaryrefslogtreecommitdiff
path: root/include/cru/base/platform/win
diff options
context:
space:
mode:
Diffstat (limited to 'include/cru/base/platform/win')
-rw-r--r--include/cru/base/platform/win/Base.h113
-rw-r--r--include/cru/base/platform/win/Stream.h66
-rw-r--r--include/cru/base/platform/win/StreamConvert.h13
-rw-r--r--include/cru/base/platform/win/Win32FileStream.h42
-rw-r--r--include/cru/base/platform/win/Win32SubProcess.h41
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