aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/cru/common/io/MemoryStream.hpp3
-rw-r--r--include/cru/common/platform/win/ComAutoInit.hpp21
-rw-r--r--include/cru/common/platform/win/StreamConvert.hpp14
-rw-r--r--include/cru/common/platform/win/Win32FileStream.hpp3
-rw-r--r--include/cru/win/graphics/direct/Factory.hpp3
-rw-r--r--src/common/CMakeLists.txt6
-rw-r--r--src/common/platform/win/BridgeComStream.cpp2
-rw-r--r--src/common/platform/win/BrigdeComStream.hpp (renamed from include/cru/common/platform/win/BrigdeComStream.hpp)9
-rw-r--r--src/common/platform/win/ComAutoInit.cpp15
-rw-r--r--src/common/platform/win/StreamConvert.cpp53
-rw-r--r--src/common/platform/win/Win32FileStream.cpp7
-rw-r--r--src/win/graphics/direct/Factory.cpp21
-rw-r--r--test/common/CMakeLists.txt5
-rw-r--r--test/common/platform/unix/UnixFileStreamTest.cpp (renamed from test/common/io/UnixFileStreamTest.cpp)0
-rw-r--r--test/common/platform/win/StreamConvertTest.cpp38
-rw-r--r--test/common/platform/win/Win32FileStreamTest.cpp (renamed from test/common/io/Win32FileStreamTest.cpp)2
16 files changed, 168 insertions, 34 deletions
diff --git a/include/cru/common/io/MemoryStream.hpp b/include/cru/common/io/MemoryStream.hpp
index e917814c..29da7b9f 100644
--- a/include/cru/common/io/MemoryStream.hpp
+++ b/include/cru/common/io/MemoryStream.hpp
@@ -31,6 +31,9 @@ class CRU_BASE_API MemoryStream : public Stream {
bool CanWrite() override;
Index Write(const std::byte* buffer, Index offset, Index size) override;
+ std::byte* GetBuffer() const { return buffer_; }
+ Index GetSize() override { return size_; }
+
private:
std::byte* buffer_ = nullptr;
Index size_ = 0;
diff --git a/include/cru/common/platform/win/ComAutoInit.hpp b/include/cru/common/platform/win/ComAutoInit.hpp
new file mode 100644
index 00000000..131f3f30
--- /dev/null
+++ b/include/cru/common/platform/win/ComAutoInit.hpp
@@ -0,0 +1,21 @@
+#pragma once
+
+#include "../../PreConfig.hpp"
+#ifdef CRU_PLATFORM_WINDOWS
+
+#include "WinPreConfig.hpp"
+#include "cru/common/Base.hpp"
+
+namespace cru::platform::win {
+class CRU_BASE_API ComAutoInit {
+ public:
+ ComAutoInit();
+
+ CRU_DELETE_COPY(ComAutoInit)
+ CRU_DELETE_MOVE(ComAutoInit)
+
+ ~ComAutoInit();
+};
+} // namespace cru::platform::win
+
+#endif
diff --git a/include/cru/common/platform/win/StreamConvert.hpp b/include/cru/common/platform/win/StreamConvert.hpp
new file mode 100644
index 00000000..80800115
--- /dev/null
+++ b/include/cru/common/platform/win/StreamConvert.hpp
@@ -0,0 +1,14 @@
+#pragma once
+#include "../../PreConfig.hpp"
+
+#ifdef CRU_PLATFORM_WINDOWS
+
+#include "../../io/Stream.hpp"
+
+#include <objidlbase.h>
+
+namespace cru::platform::win {
+CRU_BASE_API IStream* ConvertStreamToComStream(io::Stream* stream);
+}
+
+#endif
diff --git a/include/cru/common/platform/win/Win32FileStream.hpp b/include/cru/common/platform/win/Win32FileStream.hpp
index ebb23357..b5511ba3 100644
--- a/include/cru/common/platform/win/Win32FileStream.hpp
+++ b/include/cru/common/platform/win/Win32FileStream.hpp
@@ -36,6 +36,9 @@ class CRU_BASE_API Win32FileStream : public io::Stream {
void Close() override;
+ String GetPath() const { return path_; }
+ io::OpenFileFlag GetOpenFileFlags() const { return flags_; }
+
private:
void CheckClosed();
diff --git a/include/cru/win/graphics/direct/Factory.hpp b/include/cru/win/graphics/direct/Factory.hpp
index ba504f0d..4ceed7c5 100644
--- a/include/cru/win/graphics/direct/Factory.hpp
+++ b/include/cru/win/graphics/direct/Factory.hpp
@@ -3,6 +3,7 @@
#include "ImageFactory.hpp"
+#include "cru/common/platform/win/ComAutoInit.hpp"
#include "cru/platform/graphics/Base.hpp"
#include "cru/platform/graphics/Factory.hpp"
@@ -52,6 +53,8 @@ class CRU_WIN_GRAPHICS_DIRECT_API DirectGraphicsFactory
IImageFactory* GetImageFactory() override;
private:
+ platform::win::ComAutoInit com_auto_init_;
+
Microsoft::WRL::ComPtr<ID3D11Device> d3d11_device_;
Microsoft::WRL::ComPtr<ID2D1Factory2> d2d1_factory_;
Microsoft::WRL::ComPtr<ID2D1Device1> d2d1_device_;
diff --git a/src/common/CMakeLists.txt b/src/common/CMakeLists.txt
index 3294b2f0..706f0ed0 100644
--- a/src/common/CMakeLists.txt
+++ b/src/common/CMakeLists.txt
@@ -35,9 +35,13 @@ endif()
if (WIN32)
target_sources(cru_base PRIVATE
platform/win/BridgeComStream.cpp
- platform/win/Win32FileStream.cpp
+ platform/win/ComAutoInit.cpp
+ platform/win/StreamConvert.cpp
platform/win/Exception.cpp
+ platform/win/Win32FileStream.cpp
)
+
+ target_link_libraries(cru_base PUBLIC Shlwapi.lib)
endif()
if (WIN32)
diff --git a/src/common/platform/win/BridgeComStream.cpp b/src/common/platform/win/BridgeComStream.cpp
index d324a4c2..48ba8154 100644
--- a/src/common/platform/win/BridgeComStream.cpp
+++ b/src/common/platform/win/BridgeComStream.cpp
@@ -1,5 +1,5 @@
+#include "BrigdeComStream.hpp"
#include "cru/common/io/Stream.hpp"
-#include "cru/common/platform/win/BrigdeComStream.hpp"
namespace cru::platform::win {
BridgeComStream::BridgeComStream(io::Stream *stream)
diff --git a/include/cru/common/platform/win/BrigdeComStream.hpp b/src/common/platform/win/BrigdeComStream.hpp
index 38b75dae..228c16f6 100644
--- a/include/cru/common/platform/win/BrigdeComStream.hpp
+++ b/src/common/platform/win/BrigdeComStream.hpp
@@ -1,10 +1,7 @@
#pragma once
-#include "../../PreConfig.hpp"
-#ifdef CRU_PLATFORM_WINDOWS
+#include "cru/common/platform/win/WinPreConfig.hpp"
-#include "WinPreConfig.hpp"
-
-#include "../../io/Stream.hpp"
+#include "cru/common/io/Stream.hpp"
#include <objidlbase.h>
@@ -44,5 +41,3 @@ class BridgeComStream : public IStream {
ULONG ref_count_;
};
} // namespace cru::platform::win
-
-#endif
diff --git a/src/common/platform/win/ComAutoInit.cpp b/src/common/platform/win/ComAutoInit.cpp
new file mode 100644
index 00000000..e336be59
--- /dev/null
+++ b/src/common/platform/win/ComAutoInit.cpp
@@ -0,0 +1,15 @@
+#include "cru/common/platform/win/ComAutoInit.hpp"
+#include "cru/common/platform/win/Exception.hpp"
+
+#include <combaseapi.h>
+
+namespace cru::platform::win {
+ComAutoInit::ComAutoInit() {
+ const auto hresult = ::CoInitializeEx(nullptr, COINIT_APARTMENTTHREADED);
+ if (FAILED(hresult)) {
+ throw HResultError(hresult, "Failed to call CoInitializeEx.");
+ }
+}
+
+ComAutoInit::~ComAutoInit() { ::CoUninitialize(); }
+} // namespace cru::platform::win
diff --git a/src/common/platform/win/StreamConvert.cpp b/src/common/platform/win/StreamConvert.cpp
new file mode 100644
index 00000000..1d077573
--- /dev/null
+++ b/src/common/platform/win/StreamConvert.cpp
@@ -0,0 +1,53 @@
+#include "cru/common/platform/win/StreamConvert.hpp"
+#include "BrigdeComStream.hpp"
+#include "cru/common/Exception.hpp"
+#include "cru/common/io/MemoryStream.hpp"
+#include "cru/common/io/OpenFileFlag.hpp"
+#include "cru/common/platform/win/ComAutoInit.hpp"
+#include "cru/common/platform/win/Exception.hpp"
+#include "cru/common/platform/win/Win32FileStream.hpp"
+
+#include <shlwapi.h>
+#include <winnt.h>
+
+namespace cru::platform::win {
+IStream* ConvertStreamToComStream(io::Stream* stream) {
+ static ComAutoInit com_auto_init;
+
+ if (auto memory_stream = dynamic_cast<io::MemoryStream*>(stream)) {
+ return SHCreateMemStream(
+ reinterpret_cast<const BYTE*>(memory_stream->GetBuffer()),
+ memory_stream->GetSize());
+ } else if (auto file_stream = dynamic_cast<Win32FileStream*>(stream)) {
+ auto path = file_stream->GetPath();
+ auto flags = file_stream->GetOpenFileFlags();
+ DWORD grfMode = STGM_SHARE_DENY_NONE | STGM_FAILIFTHERE;
+ if (flags & io::OpenFileFlags::Read) {
+ if (flags & io::OpenFileFlags::Write) {
+ grfMode |= STGM_READWRITE;
+ } else {
+ grfMode |= STGM_READ;
+ }
+ } else {
+ if (flags & io::OpenFileFlags::Write) {
+ grfMode |= STGM_WRITE;
+ } else {
+ throw Exception(u"Stream must be readable or writable.");
+ }
+ }
+
+ IStream* result;
+
+ ThrowIfFailed(SHCreateStreamOnFileEx(
+ path.WinCStr(), grfMode, FILE_ATTRIBUTE_NORMAL, FALSE, NULL, &result));
+
+ LARGE_INTEGER position;
+ position.QuadPart = stream->Tell();
+ result->Seek(position, STREAM_SEEK_SET, NULL);
+
+ return result;
+ } else {
+ return new BridgeComStream(stream);
+ }
+}
+} // namespace cru::platform::win
diff --git a/src/common/platform/win/Win32FileStream.cpp b/src/common/platform/win/Win32FileStream.cpp
index ddf81c28..db3a1e01 100644
--- a/src/common/platform/win/Win32FileStream.cpp
+++ b/src/common/platform/win/Win32FileStream.cpp
@@ -4,6 +4,7 @@
#include "cru/common/platform/win/Exception.hpp"
#include <Windows.h>
+#include <winnt.h>
namespace cru::platform::win {
using namespace cru::io;
@@ -37,9 +38,9 @@ Win32FileStream::Win32FileStream(String path, OpenFileFlag flags)
dwCreationDisposition = OPEN_EXISTING;
}
- p_->handle =
- ::CreateFileW(path_.WinCStr(), dwDesiredAccess, 0, nullptr,
- dwCreationDisposition, FILE_ATTRIBUTE_NORMAL, nullptr);
+ p_->handle = ::CreateFileW(
+ path_.WinCStr(), dwDesiredAccess, FILE_SHARE_READ | FILE_SHARE_WRITE,
+ nullptr, dwCreationDisposition, FILE_ATTRIBUTE_NORMAL, nullptr);
if (p_->handle == INVALID_HANDLE_VALUE) {
throw Win32Error(u"Failed to call CreateFileW.");
diff --git a/src/win/graphics/direct/Factory.cpp b/src/win/graphics/direct/Factory.cpp
index cbdfe991..bc51cd1a 100644
--- a/src/win/graphics/direct/Factory.cpp
+++ b/src/win/graphics/direct/Factory.cpp
@@ -12,28 +12,11 @@
#include <utility>
namespace cru::platform::graphics::win::direct {
-namespace {
-void InitializeCom() {
- const auto hresult = ::CoInitializeEx(nullptr, COINIT_APARTMENTTHREADED);
- if (FAILED(hresult)) {
- throw HResultError(hresult, "Failed to call CoInitializeEx.");
- }
- if (hresult == S_FALSE) {
- log::Debug(
- u"Try to call CoInitializeEx, but it seems COM is already "
- u"initialized.");
- }
-}
-
-void UninitializeCom() { ::CoUninitialize(); }
-} // namespace
DirectGraphicsFactory::DirectGraphicsFactory() {
- // TODO! Detect repeated creation. Because I don't think we can create two d2d
+ // TODO: Detect repeated creation. Because I don't think we can create two d2d
// and dwrite factory so we need to prevent the "probably dangerous" behavior.
- InitializeCom();
-
UINT creation_flags = D3D11_CREATE_DEVICE_BGRA_SUPPORT;
#ifdef CRU_DEBUG
@@ -79,7 +62,7 @@ DirectGraphicsFactory::DirectGraphicsFactory() {
image_factory_ = std::make_unique<WinImageFactory>(this);
}
-DirectGraphicsFactory::~DirectGraphicsFactory() { UninitializeCom(); }
+DirectGraphicsFactory::~DirectGraphicsFactory() {}
Microsoft::WRL::ComPtr<ID2D1DeviceContext1>
DirectGraphicsFactory::CreateD2D1DeviceContext() {
diff --git a/test/common/CMakeLists.txt b/test/common/CMakeLists.txt
index 38c15000..600c18c3 100644
--- a/test/common/CMakeLists.txt
+++ b/test/common/CMakeLists.txt
@@ -8,13 +8,14 @@ target_link_libraries(cru_base_test PRIVATE cru_base cru_test_base)
if (UNIX)
target_sources(cru_base_test PRIVATE
- io/UnixFileStreamTest.cpp
+ platform/unix/UnixFileStreamTest.cpp
)
endif()
if (WIN32)
target_sources(cru_base_test PRIVATE
- io/Win32FileStreamTest.cpp
+ platform/win/StreamConvertTest.cpp
+ platform/win/Win32FileStreamTest.cpp
)
add_custom_command(TARGET cru_base_test POST_BUILD
diff --git a/test/common/io/UnixFileStreamTest.cpp b/test/common/platform/unix/UnixFileStreamTest.cpp
index cdc749ba..cdc749ba 100644
--- a/test/common/io/UnixFileStreamTest.cpp
+++ b/test/common/platform/unix/UnixFileStreamTest.cpp
diff --git a/test/common/platform/win/StreamConvertTest.cpp b/test/common/platform/win/StreamConvertTest.cpp
new file mode 100644
index 00000000..43c6f46c
--- /dev/null
+++ b/test/common/platform/win/StreamConvertTest.cpp
@@ -0,0 +1,38 @@
+#include "cru/common/io/OpenFileFlag.hpp"
+#include "cru/common/platform/win/Exception.hpp"
+#include "cru/common/platform/win/StreamConvert.hpp"
+#include "cru/common/platform/win/Win32FileStream.hpp"
+
+#include <gtest/gtest.h>
+
+#include <cstdio>
+#include <filesystem>
+
+TEST(StreamConvert, FileStreamWork) {
+ using namespace cru;
+ using namespace cru::io;
+ using namespace cru::platform::win;
+
+ auto temp_file_path =
+ (std::filesystem::temp_directory_path() / "cru_test_temp.XXXXXX")
+ .native();
+ _wmktemp(temp_file_path.data());
+
+ String path = temp_file_path;
+
+ Win32FileStream file(
+ path, OpenFileFlags::Read | OpenFileFlags::Write | OpenFileFlags::Create);
+ file.Write("abc", 3);
+
+ IStream* com_stream = ConvertStreamToComStream(&file);
+ LARGE_INTEGER position;
+ position.QuadPart = 0;
+ ThrowIfFailed(com_stream->Seek(position, SEEK_SET, nullptr));
+ auto buffer = std::make_unique<char[]>(3);
+ ThrowIfFailed(com_stream->Read(buffer.get(), 3, nullptr));
+ ASSERT_EQ(std::string_view(buffer.get(), 3), "abc");
+ com_stream->Release();
+ file.Close();
+
+ std::filesystem::remove(temp_file_path);
+}
diff --git a/test/common/io/Win32FileStreamTest.cpp b/test/common/platform/win/Win32FileStreamTest.cpp
index 0e35bb8d..deb981f9 100644
--- a/test/common/io/Win32FileStreamTest.cpp
+++ b/test/common/platform/win/Win32FileStreamTest.cpp
@@ -6,7 +6,7 @@
#include <cstdio>
#include <filesystem>
-TEST(UnixFileStream, Work) {
+TEST(Win32FileStream, Work) {
using namespace cru;
using namespace cru::io;
using namespace cru::platform::win;