Prepare launcher
This commit is contained in:
parent
f2924eee05
commit
e60ffbc9ee
19
src/client/launcher/html/dispatch.hpp
Normal file
19
src/client/launcher/html/dispatch.hpp
Normal file
@ -0,0 +1,19 @@
|
||||
#pragma once
|
||||
|
||||
|
||||
class dispatch : public IDispatch
|
||||
{
|
||||
public:
|
||||
virtual ~dispatch() = default;
|
||||
|
||||
HRESULT STDMETHODCALLTYPE GetTypeInfoCount(UINT* pctinfo) override
|
||||
{
|
||||
return S_FALSE;
|
||||
}
|
||||
|
||||
HRESULT STDMETHODCALLTYPE GetTypeInfo(UINT iTInfo, LCID lcid, ITypeInfo** ppTInfo) override
|
||||
{
|
||||
return S_FALSE;
|
||||
}
|
||||
|
||||
};
|
92
src/client/launcher/html/doc_host_ui_handler.hpp
Normal file
92
src/client/launcher/html/doc_host_ui_handler.hpp
Normal file
@ -0,0 +1,92 @@
|
||||
#pragma once
|
||||
|
||||
class doc_host_ui_handler /*_boilerplate*/ : public IDocHostUIHandler
|
||||
{
|
||||
public:
|
||||
virtual ~doc_host_ui_handler() = default;
|
||||
|
||||
HRESULT STDMETHODCALLTYPE ShowContextMenu(
|
||||
DWORD,
|
||||
POINT*,
|
||||
IUnknown*,
|
||||
IDispatch*) override
|
||||
{
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT STDMETHODCALLTYPE ShowUI(
|
||||
DWORD,
|
||||
IOleInPlaceActiveObject*,
|
||||
IOleCommandTarget*,
|
||||
IOleInPlaceFrame*,
|
||||
IOleInPlaceUIWindow*) override
|
||||
{
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT STDMETHODCALLTYPE HideUI() override
|
||||
{
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT STDMETHODCALLTYPE UpdateUI() override
|
||||
{
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT STDMETHODCALLTYPE EnableModeless(BOOL) override
|
||||
{
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT STDMETHODCALLTYPE OnDocWindowActivate(BOOL) override
|
||||
{
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT STDMETHODCALLTYPE OnFrameWindowActivate(BOOL) override
|
||||
{
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT STDMETHODCALLTYPE ResizeBorder(
|
||||
LPCRECT,
|
||||
IOleInPlaceUIWindow*,
|
||||
BOOL) override
|
||||
{
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT STDMETHODCALLTYPE TranslateAccelerator(
|
||||
LPMSG,
|
||||
const GUID*,
|
||||
DWORD) override
|
||||
{
|
||||
return S_FALSE;
|
||||
}
|
||||
|
||||
HRESULT STDMETHODCALLTYPE GetOptionKeyPath(LPOLESTR __RPC_FAR* pchKey, DWORD dw) override
|
||||
{
|
||||
return S_FALSE;
|
||||
}
|
||||
|
||||
HRESULT STDMETHODCALLTYPE GetDropTarget(
|
||||
IDropTarget*,
|
||||
IDropTarget**) override
|
||||
{
|
||||
return S_FALSE;
|
||||
}
|
||||
|
||||
|
||||
HRESULT STDMETHODCALLTYPE TranslateUrl(DWORD, OLECHAR*, OLECHAR** ppchURLOut) override
|
||||
{
|
||||
*ppchURLOut = nullptr;
|
||||
return S_FALSE;
|
||||
}
|
||||
|
||||
HRESULT STDMETHODCALLTYPE FilterDataObject(IDataObject*, IDataObject** ppDORet) override
|
||||
{
|
||||
*ppDORet = nullptr;
|
||||
return S_FALSE;
|
||||
}
|
||||
};
|
79
src/client/launcher/html/html_argument.cpp
Normal file
79
src/client/launcher/html/html_argument.cpp
Normal file
@ -0,0 +1,79 @@
|
||||
#include <std_include.hpp>
|
||||
#include "html_argument.hpp"
|
||||
|
||||
html_argument::html_argument(VARIANT* val)
|
||||
: html_argument(*val)
|
||||
{
|
||||
}
|
||||
|
||||
html_argument::html_argument(CComVariant val)
|
||||
: value_(std::move(val))
|
||||
{
|
||||
}
|
||||
|
||||
bool html_argument::is_empty() const
|
||||
{
|
||||
return this->value_.vt == VT_EMPTY;
|
||||
}
|
||||
|
||||
bool html_argument::is_string() const
|
||||
{
|
||||
if (this->is_empty()) return false;
|
||||
return this->value_.vt == VT_BSTR;
|
||||
}
|
||||
|
||||
bool html_argument::is_number() const
|
||||
{
|
||||
if (this->is_empty()) return false;
|
||||
return this->value_.vt == VT_I4;
|
||||
}
|
||||
|
||||
bool html_argument::is_bool() const
|
||||
{
|
||||
if (this->is_empty()) return false;
|
||||
return this->value_.vt == VT_BOOL;
|
||||
}
|
||||
|
||||
std::string html_argument::get_string() const
|
||||
{
|
||||
if (!this->is_string()) return {};
|
||||
std::wstring wide_string(this->value_.bstrVal);
|
||||
return std::string(wide_string.begin(), wide_string.end());
|
||||
}
|
||||
|
||||
int html_argument::get_number() const
|
||||
{
|
||||
if (!this->is_number()) return 0;
|
||||
return this->value_.intVal;
|
||||
}
|
||||
|
||||
bool html_argument::get_bool() const
|
||||
{
|
||||
if (!this->is_bool()) return false;
|
||||
return this->value_.boolVal != FALSE;
|
||||
}
|
||||
|
||||
void html_argument::copy_to(VARIANT& var) const
|
||||
{
|
||||
if (this->is_empty())
|
||||
{
|
||||
VariantInit(&var);
|
||||
}
|
||||
else
|
||||
{
|
||||
(void)VariantCopy(&var, &this->value_);
|
||||
}
|
||||
}
|
||||
|
||||
void html_argument::move_to(VARIANT* var)
|
||||
{
|
||||
if (!var)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
VARIANT& src_var = this->value_;
|
||||
memcpy(var, &src_var, sizeof(*var));
|
||||
|
||||
VariantInit(&this->value_);
|
||||
}
|
32
src/client/launcher/html/html_argument.hpp
Normal file
32
src/client/launcher/html/html_argument.hpp
Normal file
@ -0,0 +1,32 @@
|
||||
#pragma once
|
||||
|
||||
#pragma once
|
||||
|
||||
class html_argument final
|
||||
{
|
||||
public:
|
||||
html_argument() = default;
|
||||
html_argument(VARIANT* val);
|
||||
html_argument(CComVariant val);
|
||||
|
||||
bool is_empty() const;
|
||||
|
||||
bool is_string() const;
|
||||
bool is_number() const;
|
||||
bool is_bool() const;
|
||||
|
||||
std::string get_string() const;
|
||||
int get_number() const;
|
||||
bool get_bool() const;
|
||||
|
||||
const CComVariant& get() const
|
||||
{
|
||||
return this->value_;
|
||||
}
|
||||
|
||||
void copy_to(VARIANT& var) const;
|
||||
void move_to(VARIANT* var);
|
||||
|
||||
private:
|
||||
CComVariant value_{};
|
||||
};
|
371
src/client/launcher/html/html_frame.cpp
Normal file
371
src/client/launcher/html/html_frame.cpp
Normal file
@ -0,0 +1,371 @@
|
||||
#include <std_include.hpp>
|
||||
#include "html_frame.hpp"
|
||||
#include "utils/nt.hpp"
|
||||
#include "utils/hook.hpp"
|
||||
|
||||
|
||||
namespace
|
||||
{
|
||||
void* original_func{};
|
||||
GUID browser_emulation_guid{0xac969931, 0x3566, 0x4b50, {0xae, 0x48, 0x71, 0xb9, 0x6a, 0x75, 0xc8, 0x79}};
|
||||
|
||||
int WINAPI co_internet_feature_value_internal_stub(const GUID* guid, uint32_t* result)
|
||||
{
|
||||
const auto res = static_cast<decltype(co_internet_feature_value_internal_stub)*>(original_func)(guid, result);
|
||||
|
||||
if (IsEqualGUID(*guid, browser_emulation_guid))
|
||||
{
|
||||
*result = 11000;
|
||||
return 0;
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
void setup_ie_hook()
|
||||
{
|
||||
static const auto _ = []
|
||||
{
|
||||
const auto urlmon = utils::nt::library::load("urlmon.dll"s);
|
||||
const auto target = urlmon.get_iat_entry("iertutil.dll", MAKEINTRESOURCEA(700));
|
||||
|
||||
original_func = *target;
|
||||
utils::hook::set(target, co_internet_feature_value_internal_stub);
|
||||
|
||||
return 0;
|
||||
}();
|
||||
(void)_;
|
||||
}
|
||||
|
||||
void setup_ole()
|
||||
{
|
||||
static struct ole_initialzer
|
||||
{
|
||||
ole_initialzer()
|
||||
{
|
||||
if (OleInitialize(nullptr) != S_OK)
|
||||
{
|
||||
throw std::runtime_error("Unable to initialize the OLE library");
|
||||
}
|
||||
}
|
||||
|
||||
~ole_initialzer()
|
||||
{
|
||||
OleUninitialize();
|
||||
}
|
||||
} init;
|
||||
(void)init;
|
||||
}
|
||||
}
|
||||
|
||||
html_frame::html_frame()
|
||||
{
|
||||
setup_ie_hook();
|
||||
setup_ole();
|
||||
}
|
||||
|
||||
HRESULT html_frame::GetHostInfo(DOCHOSTUIINFO* pInfo)
|
||||
{
|
||||
pInfo->cbSize = sizeof(DOCHOSTUIINFO);
|
||||
pInfo->dwFlags = DOCHOSTUIFLAG_NO3DBORDER | DOCHOSTUIFLAG_DPI_AWARE | DOCHOSTUIFLAG_SCROLL_NO;
|
||||
pInfo->dwDoubleClick = DOCHOSTUIDBLCLK_DEFAULT;
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT html_frame::GetWindow(HWND* lphwnd)
|
||||
{
|
||||
*lphwnd = this->window_;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT html_frame::QueryInterface(REFIID riid, void** ppvObject)
|
||||
{
|
||||
if (IsEqualGUID(riid, IID_IDispatch))
|
||||
{
|
||||
*ppvObject = static_cast<IDispatch*>(this);
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
if (IsEqualGUID(riid, IID_IDispatch))
|
||||
{
|
||||
const auto d = get_dispatch();
|
||||
if (!d)
|
||||
{
|
||||
return E_NOINTERFACE;
|
||||
}
|
||||
|
||||
(*d).AddRef();
|
||||
*ppvObject = &*d;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
if (IsEqualGUID(riid, IID_IServiceProvider))
|
||||
{
|
||||
*ppvObject = static_cast<IServiceProvider*>(this);
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
if (IsEqualGUID(riid, IID_IInternetSecurityManager))
|
||||
{
|
||||
*ppvObject = static_cast<IInternetSecurityManager*>(this);
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
if (IsEqualGUID(riid, IID_IUnknown))
|
||||
{
|
||||
*ppvObject = static_cast<IUnknown*>(static_cast<IOleClientSite*>(this));
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
if (IsEqualGUID(riid, IID_IOleClientSite))
|
||||
{
|
||||
*ppvObject = static_cast<IOleClientSite*>(this);
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
if (IsEqualGUID(riid, IID_IOleInPlaceSite))
|
||||
{
|
||||
*ppvObject = static_cast<IOleInPlaceSite*>(this);
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
if (IsEqualGUID(riid, IID_IOleInPlaceFrame))
|
||||
{
|
||||
*ppvObject = static_cast<IOleInPlaceFrame*>(this);
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
if (IsEqualGUID(riid, IID_IDocHostUIHandler))
|
||||
{
|
||||
*ppvObject = static_cast<IDocHostUIHandler*>(this);
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
if (IsEqualGUID(riid, IID_IOleInPlaceObject) && this->browser_object_)
|
||||
{
|
||||
return this->browser_object_->QueryInterface(riid, ppvObject);
|
||||
}
|
||||
|
||||
*ppvObject = nullptr;
|
||||
return E_NOINTERFACE;
|
||||
}
|
||||
|
||||
HWND html_frame::get_window() const
|
||||
{
|
||||
return this->window_;
|
||||
}
|
||||
|
||||
CComPtr<IOleObject> html_frame::get_browser_object() const
|
||||
{
|
||||
return this->browser_object_;
|
||||
}
|
||||
|
||||
CComPtr<IWebBrowser2> html_frame::get_web_browser() const
|
||||
{
|
||||
CComPtr<IWebBrowser2> web_browser{};
|
||||
if (!this->browser_object_ || FAILED(this->browser_object_.QueryInterface(&web_browser)))
|
||||
{
|
||||
return {};
|
||||
}
|
||||
|
||||
return web_browser;
|
||||
}
|
||||
|
||||
CComPtr<IDispatch> html_frame::get_dispatch() const
|
||||
{
|
||||
const auto web_browser = this->get_web_browser();
|
||||
|
||||
CComPtr<IDispatch> dispatch{};
|
||||
if (!web_browser || FAILED(web_browser->get_Document(&dispatch)))
|
||||
{
|
||||
return {};
|
||||
}
|
||||
|
||||
return dispatch;
|
||||
}
|
||||
|
||||
CComPtr<IHTMLDocument2> html_frame::get_document() const
|
||||
{
|
||||
const auto dispatch = this->get_dispatch();
|
||||
|
||||
CComPtr<IHTMLDocument2> document{};
|
||||
if (!dispatch || FAILED(dispatch.QueryInterface(&document)))
|
||||
{
|
||||
return {};
|
||||
}
|
||||
|
||||
return document;
|
||||
}
|
||||
|
||||
void html_frame::initialize(const HWND window)
|
||||
{
|
||||
if (this->window_) return;
|
||||
this->window_ = window;
|
||||
|
||||
this->create_browser();
|
||||
this->initialize_browser();
|
||||
}
|
||||
|
||||
void html_frame::create_browser()
|
||||
{
|
||||
CComPtr<IClassFactory> class_factory{};
|
||||
if (FAILED(
|
||||
CoGetClassObject(CLSID_WebBrowser, CLSCTX_INPROC_SERVER | CLSCTX_INPROC_HANDLER, nullptr, IID_IClassFactory,
|
||||
reinterpret_cast<void **>(&class_factory))))
|
||||
{
|
||||
throw std::runtime_error("Unable to get the class factory");
|
||||
}
|
||||
|
||||
class_factory->CreateInstance(nullptr, IID_IOleObject, reinterpret_cast<void**>(&this->browser_object_));
|
||||
|
||||
if (!this->browser_object_)
|
||||
{
|
||||
throw std::runtime_error("Unable to create browser object");
|
||||
}
|
||||
}
|
||||
|
||||
void html_frame::initialize_browser()
|
||||
{
|
||||
this->browser_object_->SetClientSite(this);
|
||||
this->browser_object_->SetHostNames(L"Hostname", nullptr);
|
||||
|
||||
RECT rect;
|
||||
GetClientRect(this->get_window(), &rect);
|
||||
OleSetContainedObject(this->browser_object_, TRUE);
|
||||
|
||||
this->browser_object_->DoVerb(OLEIVERB_SHOW, nullptr, this, -1, this->get_window(), &rect);
|
||||
this->resize(rect.right, rect.bottom);
|
||||
}
|
||||
|
||||
void html_frame::resize(const DWORD width, const DWORD height) const
|
||||
{
|
||||
const auto web_browser = this->get_web_browser();
|
||||
if (web_browser)
|
||||
{
|
||||
web_browser->put_Left(0);
|
||||
web_browser->put_Top(0);
|
||||
web_browser->put_Width(width);
|
||||
web_browser->put_Height(height);
|
||||
}
|
||||
}
|
||||
|
||||
bool html_frame::load_url(const std::string& url) const
|
||||
{
|
||||
auto web_browser = this->get_web_browser();
|
||||
if (!web_browser) return false;
|
||||
|
||||
CComVariant my_url(url.data());
|
||||
return SUCCEEDED(web_browser->Navigate2(&my_url, nullptr, nullptr, nullptr, nullptr));
|
||||
}
|
||||
|
||||
bool html_frame::load_html(const std::string& html) const
|
||||
{
|
||||
if (!this->load_url("about:blank")) return false;
|
||||
|
||||
const auto document = this->get_document();
|
||||
if (!document) return false;
|
||||
|
||||
CComSafeArrayBound bound{};
|
||||
bound.SetCount(1);
|
||||
bound.SetLowerBound(0);
|
||||
|
||||
CComSafeArray<VARIANT> array(&bound, 1);
|
||||
array[0] = CComVariant(html.data());
|
||||
|
||||
document->write(array);
|
||||
document->close();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
html_argument html_frame::evaluate(const std::string& javascript) const
|
||||
{
|
||||
auto dispDoc = this->get_dispatch();
|
||||
|
||||
CComPtr<IHTMLDocument2> htmlDoc;
|
||||
dispDoc->QueryInterface(&htmlDoc);
|
||||
|
||||
CComPtr<IHTMLWindow2> htmlWindow;
|
||||
htmlDoc->get_parentWindow(&htmlWindow);
|
||||
|
||||
CComDispatchDriver dispWindow;
|
||||
htmlWindow->QueryInterface(&dispWindow);
|
||||
|
||||
CComPtr<IDispatchEx> dispexWindow;
|
||||
htmlWindow->QueryInterface(&dispexWindow);
|
||||
|
||||
DISPID dispidEval = -1;
|
||||
dispexWindow->GetDispID(CComBSTR("eval"), fdexNameCaseSensitive, &dispidEval);
|
||||
|
||||
CComVariant result{};
|
||||
CComVariant code(javascript.data());
|
||||
(void)dispWindow.Invoke1(dispidEval, &code, &result);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
int html_frame::get_callback_id(const std::string& name) const
|
||||
{
|
||||
for (auto i = 0u; i < this->callbacks_.size(); ++i)
|
||||
{
|
||||
if (this->callbacks_[i].first == name)
|
||||
{
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
html_argument html_frame::invoke_callback(const int id, const std::vector<html_argument>& params) const
|
||||
{
|
||||
if (id >= 0 && static_cast<unsigned int>(id) < this->callbacks_.size())
|
||||
{
|
||||
return this->callbacks_[id].second(params);
|
||||
}
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
void html_frame::register_callback(const std::string& name, const std::function<CComVariant(const std::vector<html_argument>&)>& callback)
|
||||
{
|
||||
this->callbacks_.emplace_back(name, callback);
|
||||
}
|
||||
|
||||
HRESULT html_frame::GetIDsOfNames(const IID& /*riid*/, LPOLESTR* rgszNames, UINT cNames, LCID /*lcid*/,
|
||||
DISPID* rgDispId)
|
||||
{
|
||||
for (unsigned int i = 0; i < cNames; ++i)
|
||||
{
|
||||
std::wstring wide_name(rgszNames[i]);
|
||||
std::string name(wide_name.begin(), wide_name.end());
|
||||
|
||||
rgDispId[i] = this->get_callback_id(name);
|
||||
}
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT html_frame::Invoke(const DISPID dispIdMember, const IID& /*riid*/, LCID /*lcid*/, WORD /*wFlags*/,
|
||||
DISPPARAMS* pDispParams,
|
||||
VARIANT* pVarResult, EXCEPINFO* /*pExcepInfo*/, UINT* /*puArgErr*/)
|
||||
{
|
||||
std::vector<html_argument> params{};
|
||||
for (auto i = pDispParams->cArgs; i > 0; --i)
|
||||
{
|
||||
auto& param = pDispParams->rgvarg[i - 1];
|
||||
params.emplace_back(param);
|
||||
}
|
||||
|
||||
auto res = this->invoke_callback(dispIdMember, params);
|
||||
res.move_to(pVarResult);
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT html_frame::GetExternal(IDispatch** ppDispatch)
|
||||
{
|
||||
*ppDispatch = this;
|
||||
return *ppDispatch ? S_OK : S_FALSE;
|
||||
}
|
82
src/client/launcher/html/html_frame.hpp
Normal file
82
src/client/launcher/html/html_frame.hpp
Normal file
@ -0,0 +1,82 @@
|
||||
#pragma once
|
||||
#include "ole_in_place_frame.hpp"
|
||||
#include "ole_in_place_site.hpp"
|
||||
#include "doc_host_ui_handler.hpp"
|
||||
#include "ole_client_site.hpp"
|
||||
#include "service_provider.hpp"
|
||||
#include "internet_security_manager.hpp"
|
||||
#include "dispatch.hpp"
|
||||
#include "html_argument.hpp"
|
||||
|
||||
class html_frame
|
||||
: doc_host_ui_handler
|
||||
, service_provider
|
||||
, internet_security_manager
|
||||
, ole_client_site
|
||||
, ole_in_place_frame
|
||||
, ole_in_place_site
|
||||
, dispatch
|
||||
{
|
||||
public:
|
||||
html_frame();
|
||||
html_frame(const html_frame&) = delete;
|
||||
html_frame& operator=(const html_frame&) = delete;
|
||||
html_frame(html_frame&&) = delete;
|
||||
html_frame& operator=(html_frame&&) = delete;
|
||||
|
||||
~html_frame() override = default;
|
||||
|
||||
void initialize(HWND window);
|
||||
|
||||
void resize(DWORD width, DWORD height) const;
|
||||
bool load_url(const std::string& url) const;
|
||||
bool load_html(const std::string& html) const;
|
||||
|
||||
html_argument evaluate(const std::string& javascript) const;
|
||||
|
||||
HWND get_window() const;
|
||||
|
||||
CComPtr<IOleObject> get_browser_object() const;
|
||||
CComPtr<IWebBrowser2> get_web_browser() const;
|
||||
CComPtr<IDispatch> get_dispatch() const;
|
||||
CComPtr<IHTMLDocument2> get_document() const;
|
||||
|
||||
int get_callback_id(const std::string& name) const;
|
||||
html_argument invoke_callback(int id, const std::vector<html_argument>& params) const;
|
||||
|
||||
void register_callback(const std::string& name, const std::function<CComVariant(const std::vector<html_argument>&)>& callback);
|
||||
|
||||
HRESULT STDMETHODCALLTYPE QueryInterface(
|
||||
REFIID riid,
|
||||
void** ppvObject) override;
|
||||
|
||||
private:
|
||||
HWND window_ = nullptr;
|
||||
CComPtr<IOleObject> browser_object_;
|
||||
|
||||
std::vector<std::pair<std::string, std::function<html_argument(const std::vector<html_argument>&)>>> callbacks_;
|
||||
|
||||
void create_browser();
|
||||
void initialize_browser();
|
||||
|
||||
HRESULT STDMETHODCALLTYPE GetHostInfo(DOCHOSTUIINFO* pInfo) override;
|
||||
HRESULT STDMETHODCALLTYPE GetWindow(HWND* lphwnd) override;
|
||||
|
||||
ULONG STDMETHODCALLTYPE AddRef() override
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
ULONG STDMETHODCALLTYPE Release() override
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
HRESULT STDMETHODCALLTYPE GetIDsOfNames(REFIID riid, LPOLESTR* rgszNames, UINT cNames, LCID lcid, DISPID* rgDispId)
|
||||
override;
|
||||
HRESULT STDMETHODCALLTYPE Invoke(DISPID dispIdMember, REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS* pDispParams,
|
||||
VARIANT* pVarResult, EXCEPINFO* pExcepInfo, UINT* puArgErr) override;
|
||||
|
||||
|
||||
HRESULT STDMETHODCALLTYPE GetExternal(IDispatch** ppDispatch) override;
|
||||
};
|
37
src/client/launcher/html/html_window.cpp
Normal file
37
src/client/launcher/html/html_window.cpp
Normal file
@ -0,0 +1,37 @@
|
||||
#include <std_include.hpp>
|
||||
#include "html_window.hpp"
|
||||
|
||||
html_window::html_window(const std::string& title, int width, int height, long flags)
|
||||
: window_(title, width, height,
|
||||
[this](window*, const UINT message, const WPARAM w_param, const LPARAM l_param) -> std::optional<LRESULT> {
|
||||
return this->processor(message, w_param, l_param);
|
||||
}, flags)
|
||||
{
|
||||
}
|
||||
|
||||
window* html_window::get_window()
|
||||
{
|
||||
return &this->window_;
|
||||
}
|
||||
|
||||
html_frame* html_window::get_html_frame()
|
||||
{
|
||||
return &this->frame_;
|
||||
}
|
||||
|
||||
std::optional<LRESULT> html_window::processor(const UINT message, const WPARAM w_param, const LPARAM l_param)
|
||||
{
|
||||
if (message == WM_SIZE)
|
||||
{
|
||||
this->frame_.resize(LOWORD(l_param), HIWORD(l_param));
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (message == WM_CREATE)
|
||||
{
|
||||
this->frame_.initialize(this->window_);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return {};
|
||||
}
|
21
src/client/launcher/html/html_window.hpp
Normal file
21
src/client/launcher/html/html_window.hpp
Normal file
@ -0,0 +1,21 @@
|
||||
#pragma once
|
||||
#include "../window.hpp"
|
||||
#include "html_frame.hpp"
|
||||
|
||||
class html_window final
|
||||
{
|
||||
public:
|
||||
html_window(const std::string& title, int width, int height,
|
||||
long flags = (WS_OVERLAPPEDWINDOW & ~(WS_THICKFRAME | WS_MAXIMIZEBOX)));
|
||||
|
||||
~html_window() = default;
|
||||
|
||||
window* get_window();
|
||||
html_frame* get_html_frame();
|
||||
|
||||
private:
|
||||
html_frame frame_{};
|
||||
window window_;
|
||||
|
||||
std::optional<LRESULT> processor(UINT message, WPARAM w_param, LPARAM l_param);
|
||||
};
|
76
src/client/launcher/html/internet_security_manager.hpp
Normal file
76
src/client/launcher/html/internet_security_manager.hpp
Normal file
@ -0,0 +1,76 @@
|
||||
#pragma once
|
||||
|
||||
class internet_security_manager : public IInternetSecurityManager
|
||||
{
|
||||
public:
|
||||
HRESULT STDMETHODCALLTYPE SetSecuritySite(
|
||||
IInternetSecurityMgrSite*) override
|
||||
{
|
||||
return INET_E_DEFAULT_ACTION;
|
||||
}
|
||||
|
||||
virtual HRESULT STDMETHODCALLTYPE GetSecuritySite(
|
||||
IInternetSecurityMgrSite**) override
|
||||
{
|
||||
return INET_E_DEFAULT_ACTION;
|
||||
}
|
||||
|
||||
virtual HRESULT STDMETHODCALLTYPE MapUrlToZone(
|
||||
LPCWSTR,
|
||||
DWORD* pdwZone,
|
||||
DWORD) override
|
||||
{
|
||||
*pdwZone = URLZONE_TRUSTED;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
virtual HRESULT STDMETHODCALLTYPE GetSecurityId(
|
||||
LPCWSTR,
|
||||
BYTE*,
|
||||
DWORD*,
|
||||
DWORD_PTR) override
|
||||
{
|
||||
return INET_E_DEFAULT_ACTION;
|
||||
}
|
||||
|
||||
virtual HRESULT STDMETHODCALLTYPE ProcessUrlAction(
|
||||
LPCWSTR,
|
||||
DWORD,
|
||||
BYTE*,
|
||||
DWORD,
|
||||
BYTE*,
|
||||
DWORD,
|
||||
DWORD,
|
||||
DWORD) override
|
||||
{
|
||||
return INET_E_DEFAULT_ACTION;
|
||||
}
|
||||
|
||||
virtual HRESULT STDMETHODCALLTYPE QueryCustomPolicy(
|
||||
LPCWSTR,
|
||||
REFGUID,
|
||||
BYTE**,
|
||||
DWORD*,
|
||||
BYTE*,
|
||||
DWORD,
|
||||
DWORD) override
|
||||
{
|
||||
return INET_E_DEFAULT_ACTION;
|
||||
}
|
||||
|
||||
HRESULT STDMETHODCALLTYPE SetZoneMapping(
|
||||
DWORD,
|
||||
LPCWSTR,
|
||||
DWORD) override
|
||||
{
|
||||
return INET_E_DEFAULT_ACTION;
|
||||
}
|
||||
|
||||
HRESULT STDMETHODCALLTYPE GetZoneMappings(
|
||||
DWORD,
|
||||
IEnumString**,
|
||||
DWORD) override
|
||||
{
|
||||
return INET_E_DEFAULT_ACTION;
|
||||
}
|
||||
};
|
38
src/client/launcher/html/ole_client_site.hpp
Normal file
38
src/client/launcher/html/ole_client_site.hpp
Normal file
@ -0,0 +1,38 @@
|
||||
#pragma once
|
||||
|
||||
class ole_client_site : public IOleClientSite
|
||||
{
|
||||
public:
|
||||
virtual ~ole_client_site() = default;
|
||||
|
||||
HRESULT STDMETHODCALLTYPE SaveObject() override
|
||||
{
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
|
||||
HRESULT STDMETHODCALLTYPE GetMoniker(DWORD, DWORD, IMoniker**) override
|
||||
{
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
|
||||
HRESULT STDMETHODCALLTYPE GetContainer(LPOLECONTAINER* ppContainer) override
|
||||
{
|
||||
*ppContainer = nullptr;
|
||||
return E_NOINTERFACE;
|
||||
}
|
||||
|
||||
HRESULT STDMETHODCALLTYPE ShowObject() override
|
||||
{
|
||||
return NOERROR;
|
||||
}
|
||||
|
||||
HRESULT STDMETHODCALLTYPE OnShowWindow(BOOL) override
|
||||
{
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
|
||||
HRESULT STDMETHODCALLTYPE RequestNewObjectLayout() override
|
||||
{
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
};
|
62
src/client/launcher/html/ole_in_place_frame.hpp
Normal file
62
src/client/launcher/html/ole_in_place_frame.hpp
Normal file
@ -0,0 +1,62 @@
|
||||
#pragma once
|
||||
|
||||
class ole_in_place_frame : public IOleInPlaceFrame
|
||||
{
|
||||
public:
|
||||
virtual ~ole_in_place_frame() = default;
|
||||
|
||||
HRESULT STDMETHODCALLTYPE ContextSensitiveHelp(BOOL) override
|
||||
{
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
|
||||
HRESULT STDMETHODCALLTYPE GetBorder(LPRECT) override
|
||||
{
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
|
||||
HRESULT STDMETHODCALLTYPE RequestBorderSpace(LPCBORDERWIDTHS) override
|
||||
{
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
|
||||
HRESULT STDMETHODCALLTYPE SetBorderSpace(LPCBORDERWIDTHS) override
|
||||
{
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
|
||||
HRESULT STDMETHODCALLTYPE SetActiveObject(IOleInPlaceActiveObject* pActiveObject, LPCOLESTR pszObjName) override
|
||||
{
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT STDMETHODCALLTYPE InsertMenus(HMENU hmenuShared, LPOLEMENUGROUPWIDTHS lpMenuWidths) override
|
||||
{
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
|
||||
HRESULT STDMETHODCALLTYPE SetMenu(HMENU, HOLEMENU, HWND) override
|
||||
{
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT STDMETHODCALLTYPE RemoveMenus(HMENU hmenuShared) override
|
||||
{
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
|
||||
HRESULT STDMETHODCALLTYPE SetStatusText(LPCOLESTR) override
|
||||
{
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT STDMETHODCALLTYPE EnableModeless(BOOL) override
|
||||
{
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT STDMETHODCALLTYPE TranslateAccelerator(LPMSG lpmsg, WORD wID) override
|
||||
{
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
};
|
89
src/client/launcher/html/ole_in_place_site.hpp
Normal file
89
src/client/launcher/html/ole_in_place_site.hpp
Normal file
@ -0,0 +1,89 @@
|
||||
#pragma once
|
||||
|
||||
class ole_in_place_site : public IOleInPlaceSite
|
||||
{
|
||||
public:
|
||||
virtual ~ole_in_place_site() = default;
|
||||
|
||||
HRESULT STDMETHODCALLTYPE ContextSensitiveHelp(BOOL) override
|
||||
{
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
|
||||
HRESULT STDMETHODCALLTYPE CanInPlaceActivate() override
|
||||
{
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT STDMETHODCALLTYPE OnInPlaceActivate() override
|
||||
{
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT STDMETHODCALLTYPE OnUIActivate() override
|
||||
{
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT STDMETHODCALLTYPE GetWindowContext(LPOLEINPLACEFRAME* lplpFrame, LPOLEINPLACEUIWINDOW* lplpDoc,
|
||||
const LPRECT lprcPosRect, const LPRECT lprcClipRect,
|
||||
const LPOLEINPLACEFRAMEINFO lpFrameInfo) override
|
||||
{
|
||||
ZeroMemory(lprcPosRect, sizeof(*lprcPosRect));
|
||||
ZeroMemory(lprcClipRect, sizeof(*lprcClipRect));
|
||||
|
||||
CComPtr<IOleInPlaceFrame> ole_in_place_frame{};
|
||||
if (FAILED(QueryInterface(IID_IOleInPlaceFrame, reinterpret_cast<void**>(&ole_in_place_frame))))
|
||||
{
|
||||
*lplpFrame = nullptr;
|
||||
*lplpDoc = nullptr;
|
||||
return E_FAIL;
|
||||
}
|
||||
|
||||
*lplpFrame = ole_in_place_frame;
|
||||
*lplpDoc = nullptr;
|
||||
|
||||
lpFrameInfo->fMDIApp = FALSE;
|
||||
lpFrameInfo->haccel = nullptr;
|
||||
lpFrameInfo->cAccelEntries = 0;
|
||||
GetWindow(&lpFrameInfo->hwndFrame);
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT STDMETHODCALLTYPE Scroll(SIZE) override
|
||||
{
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
|
||||
HRESULT STDMETHODCALLTYPE OnUIDeactivate(BOOL) override
|
||||
{
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT STDMETHODCALLTYPE OnInPlaceDeactivate() override
|
||||
{
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT STDMETHODCALLTYPE DiscardUndoState() override
|
||||
{
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
|
||||
HRESULT STDMETHODCALLTYPE DeactivateAndUndo() override
|
||||
{
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
|
||||
HRESULT STDMETHODCALLTYPE OnPosRectChange(const LPCRECT lprcPosRect) override
|
||||
{
|
||||
CComPtr<IOleInPlaceObject> in_place{};
|
||||
if (SUCCEEDED(QueryInterface(IID_IOleInPlaceObject, reinterpret_cast<void**>(&in_place))))
|
||||
{
|
||||
in_place->SetObjectRects(lprcPosRect, lprcPosRect);
|
||||
}
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
};
|
22
src/client/launcher/html/service_provider.hpp
Normal file
22
src/client/launcher/html/service_provider.hpp
Normal file
@ -0,0 +1,22 @@
|
||||
#pragma once
|
||||
|
||||
class service_provider : public IServiceProvider
|
||||
{
|
||||
public:
|
||||
virtual ~service_provider() = default;
|
||||
|
||||
HRESULT STDMETHODCALLTYPE QueryService(
|
||||
REFGUID guidService,
|
||||
REFIID riid,
|
||||
void** ppvObject) override
|
||||
{
|
||||
if (IsEqualGUID(riid, IID_IInternetSecurityManager))
|
||||
{
|
||||
return QueryInterface(riid, ppvObject);
|
||||
}
|
||||
|
||||
*ppvObject = nullptr;
|
||||
return E_NOINTERFACE;
|
||||
}
|
||||
};
|
||||
|
43
src/client/launcher/launcher.cpp
Normal file
43
src/client/launcher/launcher.cpp
Normal file
@ -0,0 +1,43 @@
|
||||
#include <std_include.hpp>
|
||||
#include <utils/nt.hpp>
|
||||
|
||||
#include "launcher.hpp"
|
||||
#include "html/html_window.hpp"
|
||||
|
||||
#include "resource.hpp"
|
||||
|
||||
namespace launcher
|
||||
{
|
||||
bool run()
|
||||
{
|
||||
bool run_game = false;
|
||||
html_window window("BOIII", 750, 430);
|
||||
|
||||
window.get_html_frame()->register_callback(
|
||||
"openUrl", [](const std::vector<html_argument>& params) -> CComVariant
|
||||
{
|
||||
if (params.empty()) return {};
|
||||
|
||||
const auto& param = params[0];
|
||||
if (!param.is_string()) return {};
|
||||
|
||||
const auto url = param.get_string();
|
||||
ShellExecuteA(nullptr, "open", url.data(), nullptr, nullptr, SW_SHOWNORMAL);
|
||||
|
||||
return {};
|
||||
});
|
||||
|
||||
window.get_html_frame()->register_callback(
|
||||
"runGame", [&](const std::vector<html_argument>& /*params*/) -> CComVariant
|
||||
{
|
||||
run_game = true;
|
||||
window.get_window()->close();
|
||||
return {};
|
||||
});
|
||||
|
||||
window.get_html_frame()->load_html(utils::nt::load_resource(MENU_MAIN));
|
||||
|
||||
window::run();
|
||||
return run_game;
|
||||
}
|
||||
}
|
6
src/client/launcher/launcher.hpp
Normal file
6
src/client/launcher/launcher.hpp
Normal file
@ -0,0 +1,6 @@
|
||||
#pragma once
|
||||
|
||||
namespace launcher
|
||||
{
|
||||
bool run();
|
||||
}
|
127
src/client/launcher/window.cpp
Normal file
127
src/client/launcher/window.cpp
Normal file
@ -0,0 +1,127 @@
|
||||
#include <std_include.hpp>
|
||||
#include "window.hpp"
|
||||
|
||||
namespace
|
||||
{
|
||||
thread_local uint32_t window_count = 0;
|
||||
}
|
||||
|
||||
window::window(const std::string& title, const int width, const int height,
|
||||
std::function<std::optional<LRESULT>(window*, UINT, WPARAM, LPARAM)> callback,
|
||||
const long flags)
|
||||
: callback_(std::move(callback))
|
||||
{
|
||||
ZeroMemory(&this->wc_, sizeof(this->wc_));
|
||||
|
||||
this->classname_ = "window-base-" + std::to_string(time(nullptr));
|
||||
|
||||
this->wc_.cbSize = sizeof(this->wc_);
|
||||
this->wc_.style = CS_HREDRAW | CS_VREDRAW;
|
||||
this->wc_.lpfnWndProc = static_processor;
|
||||
this->wc_.hInstance = GetModuleHandle(nullptr);
|
||||
this->wc_.hCursor = LoadCursor(nullptr, IDC_ARROW);
|
||||
this->wc_.hIcon = LoadIcon(this->wc_.hInstance, MAKEINTRESOURCE(102));
|
||||
this->wc_.hIconSm = this->wc_.hIcon;
|
||||
this->wc_.hbrBackground = HBRUSH(COLOR_WINDOW);
|
||||
this->wc_.lpszClassName = this->classname_.data();
|
||||
RegisterClassEx(&this->wc_);
|
||||
|
||||
const auto x = (GetSystemMetrics(SM_CXSCREEN) - width) / 2;
|
||||
const auto y = (GetSystemMetrics(SM_CYSCREEN) - height) / 2;
|
||||
|
||||
++window_count;
|
||||
|
||||
this->handle_ = CreateWindowExA(NULL, this->wc_.lpszClassName, title.data(), flags, x, y, width, height, nullptr,
|
||||
nullptr, this->wc_.hInstance, this);
|
||||
|
||||
SendMessageA(this->handle_, WM_DPICHANGED, 0, 0);
|
||||
ShowWindow(this->handle_, SW_SHOW);
|
||||
}
|
||||
|
||||
window::~window()
|
||||
{
|
||||
this->close();
|
||||
UnregisterClass(this->wc_.lpszClassName, this->wc_.hInstance);
|
||||
}
|
||||
|
||||
void window::close()
|
||||
{
|
||||
if (!this->handle_) return;
|
||||
|
||||
DestroyWindow(this->handle_);
|
||||
this->handle_ = nullptr;
|
||||
}
|
||||
|
||||
void window::run()
|
||||
{
|
||||
MSG msg{};
|
||||
while (GetMessage(&msg, nullptr, 0, 0))
|
||||
{
|
||||
TranslateMessage(&msg);
|
||||
DispatchMessage(&msg);
|
||||
}
|
||||
}
|
||||
|
||||
LRESULT window::processor(const UINT message, const WPARAM w_param, const LPARAM l_param)
|
||||
{
|
||||
if (message == WM_DPICHANGED)
|
||||
{
|
||||
const auto dpi = GetDpiForWindow(*this);
|
||||
if (dpi != this->last_dpi_)
|
||||
{
|
||||
RECT rect;
|
||||
GetWindowRect(*this, &rect);
|
||||
|
||||
const auto scale = dpi * 1.0 / this->last_dpi_;
|
||||
this->last_dpi_ = dpi;
|
||||
|
||||
const auto width = rect.right - rect.left;
|
||||
const auto height = rect.bottom - rect.top;
|
||||
|
||||
MoveWindow(*this, rect.left, rect.top, int(width * scale), int(height * scale), TRUE);
|
||||
}
|
||||
}
|
||||
|
||||
if (message == WM_DESTROY)
|
||||
{
|
||||
if (--window_count == 0)
|
||||
{
|
||||
PostQuitMessage(0);
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
if (this->callback_)
|
||||
{
|
||||
const auto res = this->callback_(this, message, w_param, l_param);
|
||||
if (res)
|
||||
{
|
||||
return *res;
|
||||
}
|
||||
}
|
||||
|
||||
return DefWindowProc(*this, message, w_param, l_param);
|
||||
}
|
||||
|
||||
LRESULT CALLBACK window::static_processor(HWND hwnd, UINT message, WPARAM w_param, LPARAM l_param)
|
||||
{
|
||||
if (message == WM_CREATE)
|
||||
{
|
||||
auto data = reinterpret_cast<LPCREATESTRUCT>(l_param);
|
||||
SetWindowLongPtrA(hwnd, GWLP_USERDATA, LONG_PTR(data->lpCreateParams));
|
||||
|
||||
reinterpret_cast<window*>(data->lpCreateParams)->handle_ = hwnd;
|
||||
}
|
||||
|
||||
const auto self = reinterpret_cast<window*>(GetWindowLongPtr(hwnd, GWLP_USERDATA));
|
||||
if (self) return self->processor(message, w_param, l_param);
|
||||
|
||||
return DefWindowProc(hwnd, message, w_param, l_param);
|
||||
}
|
||||
|
||||
|
||||
window::operator HWND() const
|
||||
{
|
||||
return this->handle_;
|
||||
}
|
29
src/client/launcher/window.hpp
Normal file
29
src/client/launcher/window.hpp
Normal file
@ -0,0 +1,29 @@
|
||||
#pragma once
|
||||
|
||||
class window
|
||||
{
|
||||
public:
|
||||
window(const std::string& title, int width, int height,
|
||||
std::function<std::optional<LRESULT>(window*, UINT, WPARAM, LPARAM)> callback,
|
||||
long flags = (WS_OVERLAPPEDWINDOW & ~(WS_THICKFRAME | WS_MAXIMIZEBOX)));
|
||||
|
||||
virtual ~window();
|
||||
|
||||
void close();
|
||||
|
||||
operator HWND() const;
|
||||
|
||||
static void run();
|
||||
|
||||
LRESULT processor(UINT message, WPARAM w_param, LPARAM l_param);
|
||||
|
||||
private:
|
||||
uint32_t last_dpi_ = 96;
|
||||
|
||||
WNDCLASSEX wc_{};
|
||||
HWND handle_ = nullptr;
|
||||
std::string classname_;
|
||||
std::function<std::optional<LRESULT>(window*, UINT, WPARAM, LPARAM)> callback_;
|
||||
|
||||
static LRESULT CALLBACK static_processor(HWND hwnd, UINT message, WPARAM w_param, LPARAM l_param);
|
||||
};
|
@ -12,6 +12,7 @@
|
||||
#include <steam/steam.hpp>
|
||||
|
||||
#include "game/game.hpp"
|
||||
#include "launcher/launcher.hpp"
|
||||
|
||||
namespace
|
||||
{
|
||||
@ -172,11 +173,11 @@ namespace
|
||||
|
||||
void enable_dpi_awareness()
|
||||
{
|
||||
const utils::nt::library user32{ "user32.dll" };
|
||||
const utils::nt::library user32{"user32.dll"};
|
||||
const auto set_dpi = user32
|
||||
? user32.get_proc<BOOL(WINAPI*)(DPI_AWARENESS_CONTEXT)>(
|
||||
"SetProcessDpiAwarenessContext")
|
||||
: nullptr;
|
||||
? user32.get_proc<BOOL(WINAPI*)(DPI_AWARENESS_CONTEXT)>(
|
||||
"SetProcessDpiAwarenessContext")
|
||||
: nullptr;
|
||||
if (set_dpi)
|
||||
{
|
||||
set_dpi(DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2);
|
||||
@ -209,6 +210,11 @@ namespace
|
||||
{
|
||||
remove_crash_file();
|
||||
|
||||
if (!launcher::run())
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
const auto client_binary = "BlackOps3.exe"s;
|
||||
const auto server_binary = "BlackOps3_UnrankedDedicatedServer.exe"s;
|
||||
const auto has_server = !utils::io::file_exists(client_binary) || utils::flags::has_flag("dedicated");
|
||||
|
@ -13,3 +13,4 @@
|
||||
#define DW_QOSCONFIG 307
|
||||
|
||||
#define TLS_DLL 308
|
||||
#define MENU_MAIN 309
|
||||
|
@ -102,6 +102,8 @@ DW_FASTFILE RCDATA "resources/dw/core_ffotd_tu32_593.ff"
|
||||
DW_KEYS RCDATA "resources/dw/keys.txt"
|
||||
DW_QOSCONFIG RCDATA "resources/dw/qosconfig4.csv"
|
||||
|
||||
MENU_MAIN RCDATA "resources/main.html"
|
||||
|
||||
#ifdef _DEBUG
|
||||
TLS_DLL RCDATA "../../build/bin/x64/Debug/tlsdll.dll"
|
||||
#else
|
||||
|
478
src/client/resources/main.html
Normal file
478
src/client/resources/main.html
Normal file
File diff suppressed because one or more lines are too long
@ -47,6 +47,7 @@
|
||||
#include <Psapi.h>
|
||||
#include <urlmon.h>
|
||||
#include <atlbase.h>
|
||||
#include <atlsafe.h>
|
||||
#include <iphlpapi.h>
|
||||
#include <wincrypt.h>
|
||||
|
||||
|
@ -72,6 +72,11 @@ namespace utils::nt
|
||||
return &this->get_nt_headers()->OptionalHeader;
|
||||
}
|
||||
|
||||
void** library::get_iat_entry(const std::string& module_name, std::string proc_name) const
|
||||
{
|
||||
return this->get_iat_entry(module_name, proc_name.data());
|
||||
}
|
||||
|
||||
std::vector<PIMAGE_SECTION_HEADER> library::get_section_headers() const
|
||||
{
|
||||
std::vector<PIMAGE_SECTION_HEADER> headers;
|
||||
@ -162,7 +167,7 @@ namespace utils::nt
|
||||
return this->module_;
|
||||
}
|
||||
|
||||
void** library::get_iat_entry(const std::string& module_name, const std::string& proc_name) const
|
||||
void** library::get_iat_entry(const std::string& module_name, const char* proc_name) const
|
||||
{
|
||||
if (!this->is_valid()) return nullptr;
|
||||
|
||||
|
@ -54,10 +54,16 @@ namespace utils::nt
|
||||
[[nodiscard]] HMODULE get_handle() const;
|
||||
|
||||
template <typename T>
|
||||
[[nodiscard]] T get_proc(const std::string& process) const
|
||||
[[nodiscard]] T get_proc(const char* process) const
|
||||
{
|
||||
if (!this->is_valid()) T{};
|
||||
return reinterpret_cast<T>(GetProcAddress(this->module_, process.data()));
|
||||
return reinterpret_cast<T>(GetProcAddress(this->module_, process));
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
[[nodiscard]] T get_proc(const std::string& process) const
|
||||
{
|
||||
return get_proc<T>(process.data());
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
@ -97,7 +103,8 @@ namespace utils::nt
|
||||
[[nodiscard]] PIMAGE_DOS_HEADER get_dos_header() const;
|
||||
[[nodiscard]] PIMAGE_OPTIONAL_HEADER get_optional_header() const;
|
||||
|
||||
[[nodiscard]] void** get_iat_entry(const std::string& module_name, const std::string& proc_name) const;
|
||||
[[nodiscard]] void** get_iat_entry(const std::string& module_name, std::string proc_name) const;
|
||||
[[nodiscard]] void** get_iat_entry(const std::string& module_name, const char* proc_name) const;
|
||||
|
||||
private:
|
||||
HMODULE module_;
|
||||
|
Loading…
Reference in New Issue
Block a user