aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorcrupest <crupest@outlook.com>2022-02-03 17:55:00 +0800
committercrupest <crupest@outlook.com>2022-02-03 17:55:00 +0800
commit5aca7b099c46a87a859f40110efce708200a4bc8 (patch)
tree76a0daef247ab2b2269eebdbbda10134f213d1ca /src
parentd15172cfe1ac8558567c1b1c10c2e671b0d1f033 (diff)
downloadcru-5aca7b099c46a87a859f40110efce708200a4bc8.tar.gz
cru-5aca7b099c46a87a859f40110efce708200a4bc8.tar.bz2
cru-5aca7b099c46a87a859f40110efce708200a4bc8.zip
...
Diffstat (limited to 'src')
-rw-r--r--src/common/CMakeLists.txt6
-rw-r--r--src/common/platform/win/BridgeComStream.cpp2
-rw-r--r--src/common/platform/win/BrigdeComStream.hpp43
-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
7 files changed, 123 insertions, 24 deletions
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/src/common/platform/win/BrigdeComStream.hpp b/src/common/platform/win/BrigdeComStream.hpp
new file mode 100644
index 00000000..228c16f6
--- /dev/null
+++ b/src/common/platform/win/BrigdeComStream.hpp
@@ -0,0 +1,43 @@
+#pragma once
+#include "cru/common/platform/win/WinPreConfig.hpp"
+
+#include "cru/common/io/Stream.hpp"
+
+#include <objidlbase.h>
+
+namespace cru::platform::win {
+class BridgeComStream : public IStream {
+ public:
+ explicit BridgeComStream(io::Stream* stream);
+
+ CRU_DELETE_COPY(BridgeComStream)
+ CRU_DELETE_MOVE(BridgeComStream)
+
+ ~BridgeComStream();
+
+ public:
+ ULONG AddRef() override;
+ ULONG Release() override;
+ HRESULT QueryInterface(REFIID riid, void** ppvObject) override;
+
+ HRESULT Read(void* pv, ULONG cb, ULONG* pcbRead) override;
+ HRESULT Write(const void* pv, ULONG cb, ULONG* pcbWritten) override;
+ HRESULT Seek(LARGE_INTEGER dlibMove, DWORD dwOrigin,
+ ULARGE_INTEGER* plibNewPosition) override;
+ HRESULT SetSize(ULARGE_INTEGER libNewSize) override;
+ HRESULT CopyTo(IStream* pstm, ULARGE_INTEGER cb, ULARGE_INTEGER* pcbRead,
+ ULARGE_INTEGER* pcbWritten) override;
+ HRESULT Commit(DWORD grfCommitFlags) override;
+ HRESULT Revert() override;
+ HRESULT LockRegion(ULARGE_INTEGER libOffset, ULARGE_INTEGER cb,
+ DWORD dwLockType) override;
+ HRESULT UnlockRegion(ULARGE_INTEGER libOffset, ULARGE_INTEGER cb,
+ DWORD dwLockType) override;
+ HRESULT Stat(STATSTG* pstatstg, DWORD grfStatFlag) override;
+ HRESULT Clone(IStream** ppstm) override;
+
+ private:
+ io::Stream* stream_;
+ ULONG ref_count_;
+};
+} // namespace cru::platform::win
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() {