mirror of https://github.com/Thracky/GlosSI
Merge branch 'v2'
commit
0780385821
@ -0,0 +1,9 @@
|
||||
SET QTDIR="C:\Qt\5.10.1\msvc2015"
|
||||
SET APPVEYOR_BUILD_FOLDER="D:\Alia5\Documents\Visual Studio Projects\GloSC"
|
||||
|
||||
"C:\Program Files\7-Zip\7z.exe" a GloSC.zip TargetConfig.ini License.txt qt-license.txt Readme.md Build_Install.md %APPVEYOR_BUILD_FOLDER%\build\Win32\Release\*.exe %APPVEYOR_BUILD_FOLDER%\build\Win32\Release\*.dll %APPVEYOR_BUILD_FOLDER%\dependencies\SFML-2.4.2-x86\bin\sfml-system-2.dll %APPVEYOR_BUILD_FOLDER%\dependencies\SFML-2.4.2-x86\bin\sfml-window-2.dll %APPVEYOR_BUILD_FOLDER%\dependencies\SFML-2.4.2-x86\bin\sfml-graphics-2.dll redist\* %QTDIR%\bin\Qt5Core.dll %QTDIR%\bin\Qt5Gui.dll %QTDIR%\bin\Qt5Widgets.dll %QTDIR%\plugins\platforms\qwindows.dll
|
||||
|
||||
"C:\Program Files\7-Zip\7z.exe" rn GloSC.zip qwindows.dll platforms\qwindows.dll
|
||||
|
||||
"C:\Program Files\7-Zip\7z.exe" rn GloSC.zip redist/libeay32.dll libeay32.dll
|
||||
"C:\Program Files\7-Zip\7z.exe" rn GloSC.zip redist/ssleay32.dll ssleay32.dll
|
@ -1,6 +0,0 @@
|
||||
SET QTDIR="C:\Qt\5.9\msvc2017_64"
|
||||
SET APPVEYOR_BUILD_FOLDER="D:\Alia5\Documents\Visual Studio Projects\GloSC"
|
||||
|
||||
"C:\Program Files\7-Zip\7z.exe" a GloSC_x64.zip TargetConfig.ini License.txt qt-license.txt Readme.md Build_Install.md %APPVEYOR_BUILD_FOLDER%\build\x64\Release\*.exe %APPVEYOR_BUILD_FOLDER%\build\Win32Only\Release\*.exe %APPVEYOR_BUILD_FOLDER%\build\Win32Only\Release\*.dll %APPVEYOR_BUILD_FOLDER%\dependencies\SFML-2.4.2-x64\bin\sfml-system-2.dll %APPVEYOR_BUILD_FOLDER%\dependencies\SFML-2.4.2-x64\bin\sfml-window-2.dll %APPVEYOR_BUILD_FOLDER%\dependencies\SFML-2.4.2-x64\bin\sfml-graphics-2.dll redist\* %QTDIR%\bin\Qt5Core.dll %QTDIR%\bin\Qt5Gui.dll %QTDIR%\bin\Qt5Widgets.dll %QTDIR%\plugins\platforms\qwindows.dll
|
||||
|
||||
"C:\Program Files\7-Zip\7z.exe" rn GloSC_x64.zip qwindows.dll platforms\qwindows.dll
|
Binary file not shown.
Binary file not shown.
@ -0,0 +1,69 @@
|
||||
/*
|
||||
Copyright 2018 Peter Repukat - FlatspotSoftware
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
#include "UpdateChecker.h"
|
||||
#include <QJsonObject>
|
||||
#include <QJsonArray>
|
||||
#include <QJsonDocument>
|
||||
#include <QString>
|
||||
#include <QDesktopServices>
|
||||
#include <qmessagebox.h>
|
||||
|
||||
|
||||
UpdateChecker::UpdateChecker(QObject* parent) : QObject(parent)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
void UpdateChecker::checkUpdate(int version)
|
||||
{
|
||||
version_ = version;
|
||||
connect(&net_manager_, SIGNAL(finished(QNetworkReply*)), this, SLOT(netRequestFinished(QNetworkReply*)));
|
||||
net_manager_.get(QNetworkRequest(QUrl(releases_url)));
|
||||
}
|
||||
|
||||
void UpdateChecker::netRequestFinished(QNetworkReply* reply) const
|
||||
{
|
||||
if (!reply->error())
|
||||
{
|
||||
auto json = QJsonDocument::fromJson(reply->readAll());
|
||||
if (!json.isNull() && json.isArray())
|
||||
{
|
||||
auto last_release_object = json.array()[0].toObject();
|
||||
|
||||
auto tag = last_release_object.take("tag_name").toString();
|
||||
auto tag_substrings = tag.split('.');
|
||||
if (tag_substrings.length() >= 3)
|
||||
{
|
||||
int version = 0;
|
||||
version = (version << 4) + static_cast<char>(std::atoi(tag_substrings[0].toStdString().data()));
|
||||
version = (version << 4) + static_cast<char>(std::atoi(tag_substrings[1].toStdString().data()));
|
||||
version = (version << 4) + static_cast<char>(std::atoi(tag_substrings[2].toStdString().data()));
|
||||
|
||||
if (version > version_)
|
||||
{
|
||||
if (QMessageBox::information(nullptr,
|
||||
"GloSC", "There is a new version available!\nDownload now?",
|
||||
QMessageBox::Yes | QMessageBox::No)
|
||||
== QMessageBox::Yes)
|
||||
{
|
||||
QDesktopServices::openUrl(QUrl(last_release_object.take("html_url").toString()));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,43 @@
|
||||
/*
|
||||
Copyright 2018 Peter Repukat - FlatspotSoftware
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <QtNetwork/QNetworkAccessManager>
|
||||
#include <QtNetwork/QNetworkRequest>
|
||||
#include <QtNetwork/QNetworkReply>
|
||||
#include <QUrl>
|
||||
#include <QDateTime>
|
||||
#include <QFile>
|
||||
|
||||
class UpdateChecker : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit UpdateChecker(QObject *parent = nullptr);
|
||||
|
||||
void checkUpdate(int version);
|
||||
|
||||
public slots:
|
||||
void netRequestFinished(QNetworkReply* reply) const;
|
||||
|
||||
private:
|
||||
|
||||
QNetworkAccessManager net_manager_;
|
||||
int version_ = 0;
|
||||
constexpr static const char* releases_url = "https://api.github.com/repos/Alia5/GloSC/releases";
|
||||
};
|
||||
|
@ -1,212 +0,0 @@
|
||||
/*
|
||||
Copyright 2016 Peter Repukat - FlatspotSoftware
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http ://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
#include "GloSC_GameLauncher.h"
|
||||
#include <qapplication.h>
|
||||
|
||||
GloSC_GameLauncher::GloSC_GameLauncher(QWidget *parent)
|
||||
: QMainWindow(parent)
|
||||
{
|
||||
ui.setupUi(this);
|
||||
|
||||
QTimer::singleShot(0, this, SLOT(hide()));
|
||||
|
||||
sharedMemInstance.setKey("GloSC_GameLauncher");
|
||||
sharedMemInstance.create(1024);
|
||||
|
||||
if (!sharedMemInstance.create(1024) && sharedMemInstance.error() == QSharedMemory::AlreadyExists)
|
||||
{
|
||||
exit(1);
|
||||
}
|
||||
|
||||
sharedMemInstance.attach();
|
||||
sharedMemInstance.lock();
|
||||
memset(sharedMemInstance.data(), NULL, 1024);
|
||||
|
||||
QBuffer buffer;
|
||||
buffer.open(QBuffer::ReadWrite);
|
||||
QDataStream out(&buffer);
|
||||
out << defaultSharedMemData;
|
||||
int size = buffer.size();
|
||||
char *to = static_cast<char*>(sharedMemInstance.data());
|
||||
const char *from = buffer.data().data();
|
||||
memcpy(to, from, qMin(sharedMemInstance.size(), size));
|
||||
|
||||
sharedMemInstance.unlock();
|
||||
|
||||
|
||||
connect(qApp, SIGNAL(aboutToQuit()), this, SLOT(isAboutToBeKilled()));
|
||||
connect(&updateTimer, SIGNAL(timeout()), this, SLOT(checkSharedMem()));
|
||||
|
||||
updateTimer.setInterval(333);
|
||||
updateTimer.start();
|
||||
}
|
||||
|
||||
void GloSC_GameLauncher::isAboutToBeKilled()
|
||||
{
|
||||
sharedMemInstance.detach();
|
||||
}
|
||||
|
||||
void GloSC_GameLauncher::checkSharedMem()
|
||||
{
|
||||
QBuffer buffer;
|
||||
QDataStream dataStream(&buffer);
|
||||
QStringList stringList;
|
||||
|
||||
sharedMemInstance.lock();
|
||||
|
||||
buffer.setData(static_cast<const char*>(sharedMemInstance.constData()), sharedMemInstance.size());
|
||||
buffer.open(QBuffer::ReadOnly);
|
||||
dataStream >> stringList;
|
||||
buffer.close();
|
||||
int i = stringList.indexOf(LaunchGame);
|
||||
if (i > -1)
|
||||
{
|
||||
if (stringList.at(i + 1) != "" && stringList.at(i + 2) != "")
|
||||
{
|
||||
QStringList args;
|
||||
QRegularExpression re("([^\\s\"']+)|\"([^\"]*)\"|'([^']*)'");
|
||||
QRegularExpressionMatchIterator ri = re.globalMatch(stringList.at(i + 3));
|
||||
while (ri.hasNext())
|
||||
{
|
||||
QRegularExpressionMatch match = ri.next();
|
||||
int mi = 1;
|
||||
while (match.captured(mi).isEmpty())
|
||||
mi++;
|
||||
args += match.captured(mi);
|
||||
}
|
||||
launchGame(stringList.at(i + 1), stringList.at(i + 2), args);
|
||||
stringList = defaultSharedMemData;
|
||||
}
|
||||
}
|
||||
|
||||
i = stringList.indexOf(IsSteamHooked);
|
||||
if (i > -1)
|
||||
{
|
||||
if (stringList.at(i + 1).toInt() > -1)
|
||||
{
|
||||
bHookedSteam = true;
|
||||
stringList.replace(i + 1, "-1");
|
||||
}
|
||||
}
|
||||
|
||||
if (pid != NULL)
|
||||
{
|
||||
if (!IsProcessRunning(pid))
|
||||
{
|
||||
pid = NULL;
|
||||
int i = stringList.indexOf(LaunchedProcessFinished) + 1;
|
||||
stringList.replace(i, "1");
|
||||
}
|
||||
}
|
||||
|
||||
buffer.open(QBuffer::ReadWrite);
|
||||
QDataStream out(&buffer);
|
||||
out << stringList;
|
||||
int size = buffer.size();
|
||||
char *to = static_cast<char*>(sharedMemInstance.data());
|
||||
const char *from = buffer.data().data();
|
||||
memcpy(to, from, qMin(sharedMemInstance.size(), size));
|
||||
buffer.close();
|
||||
|
||||
sharedMemInstance.unlock();
|
||||
|
||||
if (bHookedSteam && FindWindow(NULL, L"GloSC_OverlayWindow") == NULL)
|
||||
{
|
||||
unhookBindings();
|
||||
}
|
||||
}
|
||||
|
||||
void GloSC_GameLauncher::launchGame(QString type, QString path, QStringList args)
|
||||
{
|
||||
|
||||
if (type == LGT_Win32)
|
||||
{
|
||||
QProcess app;
|
||||
if (path.contains("\\"))
|
||||
{
|
||||
app.startDetached(path, args, path.mid(0, path.lastIndexOf("\\")), &pid);
|
||||
}
|
||||
else
|
||||
{
|
||||
app.startDetached(path, args, path.mid(0, path.lastIndexOf("/")), &pid);
|
||||
|
||||
}
|
||||
} else if (type == LGT_UWP) {
|
||||
DWORD pid = 0;
|
||||
HRESULT hr = CoInitialize(nullptr);
|
||||
std::wstring appUMId = path.toStdWString();
|
||||
if (SUCCEEDED(hr)) {
|
||||
HRESULT result = LaunchUWPApp(appUMId.c_str(), &pid);
|
||||
if (SUCCEEDED(result))
|
||||
{
|
||||
this->pid = pid;
|
||||
|
||||
}
|
||||
}
|
||||
CoUninitialize();
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
HRESULT GloSC_GameLauncher::LaunchUWPApp(LPCWSTR packageFullName, PDWORD pdwProcessId)
|
||||
{
|
||||
|
||||
CComPtr<IApplicationActivationManager> spAppActivationManager;
|
||||
HRESULT result = E_INVALIDARG;
|
||||
// Initialize IApplicationActivationManager
|
||||
result = CoCreateInstance(CLSID_ApplicationActivationManager, NULL, CLSCTX_LOCAL_SERVER, IID_IApplicationActivationManager, (LPVOID*)&spAppActivationManager);
|
||||
|
||||
if (!SUCCEEDED(result))
|
||||
return result;
|
||||
|
||||
//This call causes troubles; especially with our always in foreground overlay-window
|
||||
/*
|
||||
// This call ensures that the app is launched as the foreground window
|
||||
result = CoAllowSetForegroundWindow(spAppActivationManager, NULL);
|
||||
|
||||
|
||||
if (!SUCCEEDED(result))
|
||||
return result;
|
||||
*/
|
||||
|
||||
|
||||
CoAllowSetForegroundWindow(spAppActivationManager, NULL); //try running it regardless
|
||||
|
||||
// Launch the app
|
||||
result = spAppActivationManager->ActivateApplication(packageFullName, NULL, AO_NONE, pdwProcessId);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
bool GloSC_GameLauncher::IsProcessRunning(DWORD pid)
|
||||
{
|
||||
HANDLE process = OpenProcess(SYNCHRONIZE, FALSE, pid);
|
||||
DWORD ret = WaitForSingleObject(process, 1);
|
||||
CloseHandle(process);
|
||||
return ret == WAIT_TIMEOUT;
|
||||
}
|
||||
|
||||
void GloSC_GameLauncher::unhookBindings()
|
||||
{
|
||||
QProcess proc;
|
||||
proc.setNativeArguments(" --eject ");
|
||||
proc.start("Injector.exe", QIODevice::ReadOnly);
|
||||
proc.waitForFinished();
|
||||
bHookedSteam = false;
|
||||
}
|
||||
|
||||
|
||||
|
@ -1,86 +0,0 @@
|
||||
/*
|
||||
Copyright 2016 Peter Repukat - FlatspotSoftware
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http ://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include <Windows.h>
|
||||
#include <atlbase.h>
|
||||
#include <Shobjidl.h>
|
||||
#include <appmodel.h>
|
||||
#include <AppxPackaging.h>
|
||||
#include <psapi.h>
|
||||
|
||||
#include <QtWidgets/QMainWindow>
|
||||
#include "ui_GloSC_GameLauncher.h"
|
||||
|
||||
|
||||
#include <QTimer>
|
||||
#include <QSharedmemory>
|
||||
#include <QRegularExpression>
|
||||
#include <QBuffer>
|
||||
#include <qprocess.h>
|
||||
|
||||
#include <qmessagebox.h>
|
||||
|
||||
|
||||
class GloSC_GameLauncher : public QMainWindow
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
GloSC_GameLauncher(QWidget *parent = Q_NULLPTR);
|
||||
|
||||
public slots:
|
||||
void isAboutToBeKilled();
|
||||
|
||||
private:
|
||||
Ui::GloSC_GameLauncherClass ui;
|
||||
|
||||
const QString LaunchGame = "LaunchGame";
|
||||
const QString LGT_UWP = "UWP";
|
||||
const QString LGT_Win32 = "Win32";
|
||||
const QString LaunchedProcessFinished = "LaunchedProcessFinished";
|
||||
const QString IsSteamHooked = "IsSteamHooked";
|
||||
const QStringList defaultSharedMemData = QStringList()
|
||||
<< LaunchGame
|
||||
<< ""
|
||||
<< ""
|
||||
<< ""
|
||||
<< LaunchedProcessFinished
|
||||
<< "0"
|
||||
<< IsSteamHooked
|
||||
<< "-1";
|
||||
|
||||
|
||||
|
||||
QSharedMemory sharedMemInstance;
|
||||
QTimer updateTimer;
|
||||
|
||||
qint64 pid = NULL;
|
||||
|
||||
bool bHookedSteam = false;
|
||||
|
||||
void launchGame(QString type, QString path, QStringList args);
|
||||
|
||||
static HRESULT LaunchUWPApp(LPCWSTR packageFullName, PDWORD pdwProcessId);
|
||||
|
||||
static bool IsProcessRunning(DWORD pid);
|
||||
|
||||
void unhookBindings();
|
||||
|
||||
private slots:
|
||||
void checkSharedMem();
|
||||
|
||||
};
|
@ -1,4 +0,0 @@
|
||||
<RCC>
|
||||
<qresource prefix="GloSC_GameLauncher">
|
||||
</qresource>
|
||||
</RCC>
|
Binary file not shown.
@ -1,26 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>GloSC_GameLauncherClass</class>
|
||||
<widget class="QMainWindow" name="GloSC_GameLauncherClass">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>600</width>
|
||||
<height>400</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>GloSC_GameLauncher</string>
|
||||
</property>
|
||||
<widget class="QWidget" name="centralWidget"/>
|
||||
</widget>
|
||||
<layoutdefault spacing="6" margin="11"/>
|
||||
<resources>
|
||||
<include location="GloSC_GameLauncher.qrc"/>
|
||||
</resources>
|
||||
<connections/>
|
||||
</ui>
|
@ -1,81 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup>
|
||||
<Filter Include="Source Files">
|
||||
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
|
||||
<Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
|
||||
</Filter>
|
||||
<Filter Include="Header Files">
|
||||
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
|
||||
<Extensions>h;hh;hpp;hxx;hm;inl;inc;xsd</Extensions>
|
||||
</Filter>
|
||||
<Filter Include="Resource Files">
|
||||
<UniqueIdentifier>{D9D6E242-F8AF-46E4-B9FD-80ECBC20BA3E}</UniqueIdentifier>
|
||||
<Extensions>qrc;*</Extensions>
|
||||
<ParseFiles>false</ParseFiles>
|
||||
</Filter>
|
||||
<Filter Include="Form Files">
|
||||
<UniqueIdentifier>{99349809-55BA-4b9d-BF79-8FDBB0286EB3}</UniqueIdentifier>
|
||||
<Extensions>ui</Extensions>
|
||||
</Filter>
|
||||
<Filter Include="Resource Files">
|
||||
<UniqueIdentifier>{D9D6E242-F8AF-46E4-B9FD-80ECBC20BA3E}</UniqueIdentifier>
|
||||
<Extensions>qrc;*</Extensions>
|
||||
<ParseFiles>false</ParseFiles>
|
||||
</Filter>
|
||||
<Filter Include="Generated Files">
|
||||
<UniqueIdentifier>{71ED8ED8-ACB9-4CE9-BBE1-E00B30144E11}</UniqueIdentifier>
|
||||
<Extensions>moc;h;cpp</Extensions>
|
||||
<SourceControlFiles>False</SourceControlFiles>
|
||||
</Filter>
|
||||
<Filter Include="Generated Files\Debug">
|
||||
<UniqueIdentifier>{1e9bf489-17aa-4034-b073-a718c40b9df3}</UniqueIdentifier>
|
||||
<Extensions>cpp;moc</Extensions>
|
||||
<SourceControlFiles>False</SourceControlFiles>
|
||||
</Filter>
|
||||
<Filter Include="Generated Files\Release">
|
||||
<UniqueIdentifier>{2f9e545c-e06b-44d9-ba46-8715517190c6}</UniqueIdentifier>
|
||||
<Extensions>cpp;moc</Extensions>
|
||||
<SourceControlFiles>False</SourceControlFiles>
|
||||
</Filter>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="main.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="GloSC_GameLauncher.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="GeneratedFiles\Debug\moc_GloSC_GameLauncher.cpp">
|
||||
<Filter>Generated Files\Debug</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="GeneratedFiles\Release\moc_GloSC_GameLauncher.cpp">
|
||||
<Filter>Generated Files\Release</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="GeneratedFiles\qrc_GloSC_GameLauncher.cpp">
|
||||
<Filter>Generated Files</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<CustomBuild Include="GloSC_GameLauncher.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</CustomBuild>
|
||||
<CustomBuild Include="GloSC_GameLauncher.ui">
|
||||
<Filter>Form Files</Filter>
|
||||
</CustomBuild>
|
||||
<CustomBuild Include="GloSC_GameLauncher.qrc">
|
||||
<Filter>Resource Files</Filter>
|
||||
</CustomBuild>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="GeneratedFiles\ui_GloSC_GameLauncher.h">
|
||||
<Filter>Generated Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="resource.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ResourceCompile Include="GloSC_GameLauncher.rc" />
|
||||
</ItemGroup>
|
||||
</Project>
|
@ -1,14 +0,0 @@
|
||||
//{{NO_DEPENDENCIES}}
|
||||
// Microsoft Visual C++ generated include file.
|
||||
// Used by GloSC_GameLauncher.rc
|
||||
|
||||
// Next default values for new objects
|
||||
//
|
||||
#ifdef APSTUDIO_INVOKED
|
||||
#ifndef APSTUDIO_READONLY_SYMBOLS
|
||||
#define _APS_NEXT_RESOURCE_VALUE 101
|
||||
#define _APS_NEXT_COMMAND_VALUE 40001
|
||||
#define _APS_NEXT_CONTROL_VALUE 1001
|
||||
#define _APS_NEXT_SYMED_VALUE 101
|
||||
#endif
|
||||
#endif
|
Binary file not shown.
@ -1,38 +1,41 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup>
|
||||
<Filter Include="Quelldateien">
|
||||
<Filter Include="Source Files">
|
||||
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
|
||||
<Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
|
||||
</Filter>
|
||||
<Filter Include="Headerdateien">
|
||||
<Filter Include="Header Files">
|
||||
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
|
||||
<Extensions>h;hh;hpp;hxx;hm;inl;inc;xsd</Extensions>
|
||||
</Filter>
|
||||
<Filter Include="Ressourcendateien">
|
||||
<Filter Include="Resource Files">
|
||||
<UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
|
||||
<Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
|
||||
</Filter>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="main.cpp">
|
||||
<Filter>Quelldateien</Filter>
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Injector.cpp">
|
||||
<Filter>Quelldateien</Filter>
|
||||
<ClCompile Include="..\common\Injector.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="Injector.h">
|
||||
<Filter>Headerdateien</Filter>
|
||||
<ClInclude Include="..\common\Injector.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\common\process_alive.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="resource.h">
|
||||
<Filter>Headerdateien</Filter>
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ResourceCompile Include="Injector.rc">
|
||||
<Filter>Ressourcendateien</Filter>
|
||||
<ResourceCompile Include="GloSC_Watchdog.rc">
|
||||
<Filter>Resource Files</Filter>
|
||||
</ResourceCompile>
|
||||
</ItemGroup>
|
||||
</Project>
|
Binary file not shown.
@ -1,6 +1,7 @@
|
||||
//{{NO_DEPENDENCIES}}
|
||||
// Microsoft Visual C++ generated include file.
|
||||
// Used by Injector.rc
|
||||
// Used by GloSC_Watchdog.rc
|
||||
|
||||
|
||||
// Next default values for new objects
|
||||
//
|
@ -0,0 +1,135 @@
|
||||
; Script generated by the Inno Setup Script Wizard.
|
||||
; SEE THE DOCUMENTATION FOR DETAILS ON CREATING INNO SETUP SCRIPT FILES!
|
||||
|
||||
#define MyAppName "GloSC"
|
||||
#define MyAppVersion "2.0.0"
|
||||
#define MyAppPublisher "Peter Repukat - FlatspotSoftware"
|
||||
#define MyAppURL "htpp://github.com/Alia5/GloSC"
|
||||
#define MyAppExeName "GloSC.exe"
|
||||
#define GloSCLauncherName "GloSC_GameLauncher.exe"
|
||||
|
||||
[Setup]
|
||||
; NOTE: The value of AppId uniquely identifies this application.
|
||||
; Do not use the same AppId value in installers for other applications.
|
||||
; (To generate a new GUID, click Tools | Generate GUID inside the IDE.)
|
||||
AppId={{60BEAC2A-F5B7-4C81-9EB6-CF9FE75E7329}}
|
||||
AppName={#MyAppName}
|
||||
AppVersion={#MyAppVersion}
|
||||
;AppVerName={#MyAppName} {#MyAppVersion}
|
||||
AppPublisher={#MyAppPublisher}
|
||||
AppPublisherURL={#MyAppURL}
|
||||
AppSupportURL={#MyAppURL}
|
||||
AppUpdatesURL={#MyAppURL}
|
||||
DefaultDirName={pf}\{#MyAppName}
|
||||
DefaultGroupName={#MyAppName}
|
||||
OutputDir=installer
|
||||
LicenseFile=License.txt
|
||||
InfoBeforeFile=Readme.md
|
||||
OutputBaseFilename=GloSC-installer
|
||||
PrivilegesRequired=admin
|
||||
Compression=lzma
|
||||
SolidCompression=yes
|
||||
|
||||
[Languages]
|
||||
Name: "english"; MessagesFile: "compiler:Default.isl"
|
||||
|
||||
[Tasks]
|
||||
Name: "desktopicon"; Description: "{cm:CreateDesktopIcon}"; GroupDescription: "{cm:AdditionalIcons}"; Flags: unchecked
|
||||
|
||||
[Files]
|
||||
Source: "build\Win32\Release\GloSC.exe"; DestDir: "{app}"; Flags: ignoreversion;
|
||||
Source: "build\Win32\Release\GloSC_Watchdog.exe"; DestDir: "{app}"; Flags: ignoreversion
|
||||
Source: "build\Win32\Release\SteamTarget.exe"; DestDir: "{app}"; Flags: ignoreversion
|
||||
Source: "dependencies\SFML-2.4.2-x86\bin\sfml-system-2.dll"; DestDir: "{app}"; Flags: ignoreversion
|
||||
Source: "dependencies\SFML-2.4.2-x86\bin\sfml-window-2.dll"; DestDir: "{app}"; Flags: ignoreversion
|
||||
Source: "dependencies\SFML-2.4.2-x86\bin\sfml-graphics-2.dll"; DestDir: "{app}"; Flags: ignoreversion
|
||||
Source: "License.txt"; DestDir: "{app}"; Flags: ignoreversion
|
||||
Source: "C:\Qt\5.10.1\msvc2015\bin\Qt5Core.dll"; DestDir: "{app}"; Flags: ignoreversion
|
||||
Source: "C:\Qt\5.10.1\msvc2015\bin\Qt5Gui.dll"; DestDir: "{app}"; Flags: ignoreversion
|
||||
Source: "C:\Qt\5.10.1\msvc2015\bin\Qt5Widgets.dll"; DestDir: "{app}"; Flags: ignoreversion
|
||||
Source: "C:\Qt\5.10.1\msvc2015\bin\Qt5Network.dll"; DestDir: "{app}"; Flags: ignoreversion
|
||||
Source: "build\Win32\Release\EnforceBindingDLL.dll"; DestDir: "{app}"; Flags: ignoreversion
|
||||
Source: "qt-license.txt"; DestDir: "{app}"; Flags: ignoreversion
|
||||
Source: "Readme.md"; DestDir: "{app}"; Flags: ignoreversion
|
||||
Source: "TargetConfig.ini"; DestDir: "{app}"; Flags: ignoreversion
|
||||
Source: "C:\Qt\5.10.1\msvc2015\plugins\platforms\qwindows.dll"; DestDir: "{app}\platforms"; Flags: ignoreversion
|
||||
Source: "redist\vc_redist_x86.exe"; DestDir: "{app}\redist"; Flags: ignoreversion
|
||||
Source: "redist\Install_Update_ViGEm.ps1"; DestDir: "{app}\redist"; Flags: ignoreversion
|
||||
Source: "redist\libeay32.dll"; DestDir: "{app}"; Flags: ignoreversion
|
||||
Source: "redist\ssleay32.dll"; DestDir: "{app}"; Flags: ignoreversion
|
||||
Source: "redist\OpenSSL License.txt"; DestDir: "{app}"; Flags: ignoreversion
|
||||
|
||||
|
||||
[Icons]
|
||||
Name: "{group}\{#MyAppName}"; Filename: "{app}\{#MyAppExeName}"
|
||||
Name: "{group}\{cm:UninstallProgram,{#MyAppName}}"; Filename: "{uninstallexe}"
|
||||
Name: "{commondesktop}\{#MyAppName}"; Filename: "{app}\{#MyAppExeName}"; Tasks: desktopicon
|
||||
|
||||
[Run]
|
||||
Filename: "{app}\redist\vc_redist_x86.exe"; Parameters: "/quiet /install"; Description: "Installing Redist. packages"; Flags: runascurrentuser;
|
||||
Filename: "{win}\sysnative\WindowsPowerShell\v1.0\powershell.exe"; Parameters: "&'{app}\redist\Install_Update_ViGEm.ps1'"; Description: "Installing ViGEm Driver..."; Flags: runascurrentuser
|
||||
Filename: "{app}\{#MyAppExeName}"; Description: "{cm:LaunchProgram,{#StringChange(MyAppName, '&', '&&')}}"; Flags: runascurrentuser nowait postinstall skipifsilent
|
||||
|
||||
|
||||
[InstallDelete]
|
||||
Type: files; Name: "{app}"
|
||||
|
||||
[Code]
|
||||
/////////////////////////////////////////////////////////////////////
|
||||
function GetUninstallString(): String;
|
||||
var
|
||||
sUnInstPath: String;
|
||||
sUnInstallString: String;
|
||||
begin
|
||||
sUnInstPath := ExpandConstant('Software\Microsoft\Windows\CurrentVersion\Uninstall\{#emit SetupSetting("60BEAC2A-F5B7-4C81-9EB6-CF9FE75E7329")}_is1');
|
||||
sUnInstallString := '';
|
||||
if not RegQueryStringValue(HKLM, sUnInstPath, 'UninstallString', sUnInstallString) then
|
||||
RegQueryStringValue(HKCU, sUnInstPath, 'UninstallString', sUnInstallString);
|
||||
Result := sUnInstallString;
|
||||
end;
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////
|
||||
function IsUpgrade(): Boolean;
|
||||
begin
|
||||
Result := (GetUninstallString() <> '');
|
||||
end;
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////
|
||||
function UnInstallOldVersion(): Integer;
|
||||
var
|
||||
sUnInstallString: String;
|
||||
iResultCode: Integer;
|
||||
begin
|
||||
// Return Values:
|
||||
// 1 - uninstall string is empty
|
||||
// 2 - error executing the UnInstallString
|
||||
// 3 - successfully executed the UnInstallString
|
||||
|
||||
// default return value
|
||||
Result := 0;
|
||||
|
||||
// get the uninstall string of the old app
|
||||
sUnInstallString := GetUninstallString();
|
||||
if sUnInstallString <> '' then begin
|
||||
sUnInstallString := RemoveQuotes(sUnInstallString);
|
||||
if Exec(sUnInstallString, '/SILENT /NORESTART /SUPPRESSMSGBOXES','', SW_HIDE, ewWaitUntilTerminated, iResultCode) then
|
||||
Result := 3
|
||||
else
|
||||
Result := 2;
|
||||
end else
|
||||
Result := 1;
|
||||
end;
|
||||
|
||||
/////////////////////////////////////////////////////////////////////
|
||||
procedure CurStepChanged(CurStep: TSetupStep);
|
||||
begin
|
||||
if (CurStep=ssInstall) then
|
||||
begin
|
||||
if (IsUpgrade()) then
|
||||
begin
|
||||
UnInstallOldVersion();
|
||||
end;
|
||||
end;
|
||||
end;
|
@ -1,104 +0,0 @@
|
||||
; Script generated by the Inno Setup Script Wizard.
|
||||
; SEE THE DOCUMENTATION FOR DETAILS ON CREATING INNO SETUP SCRIPT FILES!
|
||||
|
||||
#define MyAppName "GloSC"
|
||||
#define MyAppVersion "1.4.2"
|
||||
#define MyAppPublisher "Peter Repukat - FlatspotSoftware"
|
||||
#define MyAppURL "htpp://github.com/Alia5/GloSC"
|
||||
#define MyAppExeName "GloSC.exe"
|
||||
#define GloSCLauncherName "GloSC_GameLauncher.exe"
|
||||
|
||||
[Setup]
|
||||
; NOTE: The value of AppId uniquely identifies this application.
|
||||
; Do not use the same AppId value in installers for other applications.
|
||||
; (To generate a new GUID, click Tools | Generate GUID inside the IDE.)
|
||||
AppId={{60BEAC2A-F5B7-4C81-9EB6-CF9FE75E7329}}
|
||||
AppName={#MyAppName}
|
||||
AppVersion={#MyAppVersion}
|
||||
;AppVerName={#MyAppName} {#MyAppVersion}
|
||||
AppPublisher={#MyAppPublisher}
|
||||
AppPublisherURL={#MyAppURL}
|
||||
AppSupportURL={#MyAppURL}
|
||||
AppUpdatesURL={#MyAppURL}
|
||||
DefaultDirName={pf}\{#MyAppName}
|
||||
DefaultGroupName={#MyAppName}
|
||||
OutputDir=installer
|
||||
LicenseFile=License.txt
|
||||
InfoBeforeFile=Readme.md
|
||||
OutputBaseFilename=GloSC-installer_x64
|
||||
PrivilegesRequired=admin
|
||||
Compression=lzma
|
||||
SolidCompression=yes
|
||||
ArchitecturesInstallIn64BitMode=x64
|
||||
|
||||
[Languages]
|
||||
Name: "english"; MessagesFile: "compiler:Default.isl"
|
||||
|
||||
[Tasks]
|
||||
Name: "desktopicon"; Description: "{cm:CreateDesktopIcon}"; GroupDescription: "{cm:AdditionalIcons}"; Flags: unchecked
|
||||
|
||||
[Files]
|
||||
Source: "build\x64\Release\GloSC.exe"; DestDir: "{app}"; Flags: ignoreversion
|
||||
Source: "build\x64\Release\GloSC_GameLauncher.exe"; DestDir: "{app}"; Flags: ignoreversion
|
||||
Source: "build\x64\Release\SteamTarget.exe"; DestDir: "{app}"; Flags: ignoreversion
|
||||
Source: "dependencies\SFML-2.4.2-x64\bin\sfml-system-2.dll"; DestDir: "{app}"; Flags: ignoreversion
|
||||
Source: "dependencies\SFML-2.4.2-x64\bin\sfml-window-2.dll"; DestDir: "{app}"; Flags: ignoreversion
|
||||
Source: "dependencies\SFML-2.4.2-x64\bin\sfml-graphics-2.dll"; DestDir: "{app}"; Flags: ignoreversion
|
||||
Source: "License.txt"; DestDir: "{app}"; Flags: ignoreversion
|
||||
Source: "C:\Qt\5.9\msvc2017_64\bin\Qt5Core.dll"; DestDir: "{app}"; Flags: ignoreversion
|
||||
Source: "C:\Qt\5.9\msvc2017_64\bin\Qt5Gui.dll"; DestDir: "{app}"; Flags: ignoreversion
|
||||
Source: "C:\Qt\5.9\msvc2017_64\bin\Qt5Widgets.dll"; DestDir: "{app}"; Flags: ignoreversion
|
||||
Source: "build\Win32Only\Release\EnforceBindingDLL.dll"; DestDir: "{app}"; Flags: ignoreversion
|
||||
Source: "build\Win32Only\Release\Injector.exe"; DestDir: "{app}"; Flags: ignoreversion
|
||||
Source: "qt-license.txt"; DestDir: "{app}"; Flags: ignoreversion
|
||||
Source: "Readme.md"; DestDir: "{app}"; Flags: ignoreversion
|
||||
Source: "TargetConfig.ini"; DestDir: "{app}"; Flags: ignoreversion
|
||||
Source: "C:\Qt\5.9\msvc2017_64\plugins\platforms\qwindows.dll"; DestDir: "{app}\platforms"; Flags: ignoreversion
|
||||
Source: "redist\vc_redist_x64.exe"; DestDir: "{app}\redist"; Flags: ignoreversion
|
||||
Source: "redist\vc_redist_x86.exe"; DestDir: "{app}\redist"; Flags: ignoreversion
|
||||
Source: "redist\Install_Update_ViGEm.ps1"; DestDir: "{app}\redist"; Flags: ignoreversion
|
||||
|
||||
|
||||
[Icons]
|
||||
Name: "{group}\{#MyAppName}"; Filename: "{app}\{#MyAppExeName}"
|
||||
Name: "{group}\{cm:UninstallProgram,{#MyAppName}}"; Filename: "{uninstallexe}"
|
||||
Name: "{commondesktop}\{#MyAppName}"; Filename: "{app}\{#MyAppExeName}"; Tasks: desktopicon
|
||||
|
||||
[Run]
|
||||
Filename: "{app}\redist\vc_redist_x64.exe"; Parameters: "/quiet /install"; Description: "Installing Redist. packages"; Flags: runascurrentuser
|
||||
Filename: "{app}\redist\vc_redist_x86.exe"; Parameters: "/quiet /install"; Description: "Installing Redist. packages"; Flags: runascurrentuser
|
||||
Filename: "{win}\sysnative\WindowsPowerShell\v1.0\powershell.exe"; Parameters: "&'{app}\redist\Install_Update_ViGEm.ps1'"; Description: "Installing ViGEm Driver..."; Flags: runascurrentuser
|
||||
Filename: "{sys}\schtasks.exe"; Parameters: "/delete /f /tn ""GloSC_GameLauncher"""; Flags: runascurrentuser
|
||||
Filename: "{app}\{#GloSCLauncherName}"; Description: "Running GameLauncher"; Flags: nowait
|
||||
Filename: "{app}\{#MyAppExeName}"; Description: "{cm:LaunchProgram,{#StringChange(MyAppName, '&', '&&')}}"; Flags: runascurrentuser nowait postinstall skipifsilent
|
||||
|
||||
|
||||
[Registry]
|
||||
Root: HKCU; Subkey: "SOFTWARE\Microsoft\Windows\CurrentVersion\Run"; ValueType: string; ValueName: "GloSC-GameLauncher"; ValueData: """{app}\GloSC_GameLauncher.exe"""; Flags: uninsdeletevalue
|
||||
|
||||
[InstallDelete]
|
||||
Type: files; Name: "{app}"
|
||||
|
||||
|
||||
[UninstallRun]
|
||||
Filename: "{app}\redist\devcon_x64.exe"; Parameters: "remove Root\ViGEmBus"; Flags: runascurrentuser
|
||||
Filename: "{sys}\taskkill.exe"; Parameters: "/T /F /IM {#GloSCLauncherName}";
|
||||
Filename: "{sys}\schtasks.exe"; Parameters: "/delete /f /tn ""GloSC_GameLauncher"""; Flags: runascurrentuser
|
||||
|
||||
|
||||
|
||||
; Preinstallation Stuff...
|
||||
[Code]
|
||||
function PrepareToInstall(var NeedsRestart: Boolean): String;
|
||||
var
|
||||
ResultCode: integer;
|
||||
begin
|
||||
|
||||
// Kill Program and wait for it to terminate
|
||||
Exec(ExpandConstant('{sys}\taskkill.exe'), '/T /F /IM {#GloSCLauncherName}', '', SW_SHOW,
|
||||
ewWaitUntilTerminated, ResultCode)
|
||||
|
||||
// Proceed Setup
|
||||
Result := '';
|
||||
|
||||
end;
|
@ -1,132 +0,0 @@
|
||||
#include "Injector.h"
|
||||
|
||||
#include <iostream>
|
||||
|
||||
void Injector::TakeDebugPrivilege()
|
||||
{
|
||||
HANDLE hProcess = GetCurrentProcess(), hToken;
|
||||
TOKEN_PRIVILEGES priv;
|
||||
LUID luid = { NULL };
|
||||
|
||||
OpenProcessToken(hProcess, TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken);
|
||||
LookupPrivilegeValue(0, SE_DEBUG_NAME, &luid);
|
||||
|
||||
priv.PrivilegeCount = 1;
|
||||
priv.Privileges[0].Luid = luid;
|
||||
priv.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
|
||||
AdjustTokenPrivileges(hToken, false, &priv, sizeof(priv), NULL, NULL);
|
||||
|
||||
CloseHandle(hToken);
|
||||
CloseHandle(hProcess);
|
||||
}
|
||||
|
||||
int Injector::Inject(DWORD pid, std::wstring &libPath)
|
||||
{
|
||||
HANDLE hProcess = NULL, allocAddress = NULL, hRemoteThread = NULL;
|
||||
LPTHREAD_START_ROUTINE pfnThreadRtn = NULL;
|
||||
|
||||
size_t pathSize = (libPath.length() + 1) * sizeof(wchar_t);
|
||||
|
||||
hProcess = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_CREATE_THREAD | PROCESS_VM_OPERATION | PROCESS_VM_WRITE, false, pid);
|
||||
|
||||
if (!hProcess)
|
||||
return 1;
|
||||
|
||||
allocAddress = VirtualAllocEx(hProcess, NULL, pathSize, MEM_COMMIT, PAGE_READWRITE);
|
||||
|
||||
if (!allocAddress)
|
||||
{
|
||||
CloseHandle(hProcess);
|
||||
return 2;
|
||||
}
|
||||
|
||||
if (!WriteProcessMemory(hProcess, (LPVOID)allocAddress, libPath.c_str(), pathSize, NULL))
|
||||
{
|
||||
VirtualFreeEx(hProcess, allocAddress, pathSize, MEM_DECOMMIT);
|
||||
CloseHandle(hProcess);
|
||||
return 3;
|
||||
}
|
||||
|
||||
pfnThreadRtn = reinterpret_cast<PTHREAD_START_ROUTINE>(GetProcAddress(GetModuleHandle(L"Kernel32"), "LoadLibraryW"));
|
||||
if (!pfnThreadRtn)
|
||||
{
|
||||
VirtualFreeEx(hProcess, allocAddress, pathSize, MEM_DECOMMIT);
|
||||
CloseHandle(hProcess);
|
||||
return 4;
|
||||
}
|
||||
|
||||
hRemoteThread = CreateRemoteThread(hProcess, NULL, 0, pfnThreadRtn, allocAddress, 0, NULL);
|
||||
|
||||
if (!hRemoteThread)
|
||||
{
|
||||
VirtualFreeEx(hProcess, allocAddress, pathSize, MEM_DECOMMIT);
|
||||
CloseHandle(hProcess);
|
||||
return 5;
|
||||
}
|
||||
|
||||
WaitForSingleObject(hRemoteThread, INFINITE);
|
||||
|
||||
CloseHandle(hRemoteThread);
|
||||
VirtualFreeEx(hProcess, allocAddress, pathSize, MEM_DECOMMIT);
|
||||
CloseHandle(hProcess);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int Injector::Eject(DWORD pid, std::wstring &libPath)
|
||||
{
|
||||
HANDLE hProcess = NULL, hRemoteThread = NULL;
|
||||
HMODULE hLibMod = NULL;
|
||||
LPTHREAD_START_ROUTINE pfnThreadRtn = NULL;
|
||||
|
||||
|
||||
if (!findModule(pid, libPath, hLibMod))
|
||||
return 2;
|
||||
|
||||
hProcess = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_CREATE_THREAD | PROCESS_VM_OPERATION, false, pid);
|
||||
if (!hProcess)
|
||||
return 1;
|
||||
|
||||
pfnThreadRtn = (PTHREAD_START_ROUTINE) GetProcAddress(GetModuleHandle(L"Kernel32"), "FreeLibrary");
|
||||
|
||||
if (!pfnThreadRtn)
|
||||
{
|
||||
CloseHandle(hProcess);
|
||||
return 3;
|
||||
}
|
||||
|
||||
hRemoteThread = CreateRemoteThread(hProcess, NULL, NULL, pfnThreadRtn, hLibMod, NULL, NULL);
|
||||
|
||||
if (!hRemoteThread)
|
||||
return 4;
|
||||
|
||||
WaitForSingleObject(hRemoteThread, INFINITE);
|
||||
|
||||
CloseHandle(hProcess);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool Injector::findModule(DWORD pid, std::wstring &libPath, HMODULE &hMod)
|
||||
{
|
||||
MODULEENTRY32W entry = { sizeof(entry) };
|
||||
HANDLE snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, pid);
|
||||
|
||||
if (Module32FirstW(snapshot, &entry) == TRUE)
|
||||
{
|
||||
while (Module32NextW(snapshot, &entry) == TRUE)
|
||||
{
|
||||
std::wstring ModuleName(entry.szModule);
|
||||
std::wstring ExePath(entry.szExePath);
|
||||
if (ModuleName == libPath || ExePath == libPath)
|
||||
{
|
||||
hMod = (HMODULE)entry.modBaseAddr;
|
||||
CloseHandle(snapshot);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
CloseHandle(snapshot);
|
||||
return false;
|
||||
}
|
||||
|
@ -1,20 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include <windows.h>
|
||||
#include <tlhelp32.h>
|
||||
#include <string>
|
||||
|
||||
class Injector {
|
||||
|
||||
|
||||
public:
|
||||
static void TakeDebugPrivilege();
|
||||
static int Inject(DWORD pid, std::wstring &libPath);
|
||||
static int Eject(DWORD pid, std::wstring &libPath);
|
||||
|
||||
private:
|
||||
|
||||
static bool findModule(DWORD pid, std::wstring &libPath, HMODULE &hMod);
|
||||
|
||||
|
||||
};
|
@ -1,97 +0,0 @@
|
||||
#include <iostream>
|
||||
#include <Windows.h>
|
||||
#include <tlhelp32.h>
|
||||
#include "Injector.h"
|
||||
|
||||
#define dllName L"EnforceBindingDLL.dll";
|
||||
|
||||
int wmain(int argc, wchar_t* argv[])
|
||||
{
|
||||
if (argc < 2)
|
||||
{
|
||||
std::wcout << "Missing arguments" << std::endl;
|
||||
return 1;
|
||||
}
|
||||
|
||||
Injector::TakeDebugPrivilege();
|
||||
|
||||
wchar_t wcPath[MAX_PATH];
|
||||
GetModuleFileName(GetModuleHandle(NULL), wcPath, MAX_PATH);
|
||||
std::wstring path(wcPath);
|
||||
std::wstring libPath = path.substr(0, path.find_last_of(L"\\")+1) + dllName;
|
||||
|
||||
DWORD pid = NULL;
|
||||
|
||||
PROCESSENTRY32 entry;
|
||||
entry.dwSize = sizeof(PROCESSENTRY32);
|
||||
HANDLE snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, NULL);
|
||||
if (Process32First(snapshot, &entry) == TRUE)
|
||||
{
|
||||
while (Process32Next(snapshot, &entry) == TRUE)
|
||||
{
|
||||
if (_wcsicmp(entry.szExeFile, L"steam.exe") == 0)
|
||||
{
|
||||
pid = entry.th32ProcessID;
|
||||
}
|
||||
}
|
||||
}
|
||||
CloseHandle(snapshot);
|
||||
|
||||
if (pid == NULL)
|
||||
{
|
||||
std::wcout << "Can't detect Steam.exe running" << std::endl;
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (std::wstring(argv[1]).find(L"--inject") != std::wstring::npos)
|
||||
{
|
||||
int result = Injector::Inject(pid, libPath);
|
||||
switch (result)
|
||||
{
|
||||
case 0:
|
||||
std::wcout << "Inject success!" << std::endl;
|
||||
break;
|
||||
case 1:
|
||||
std::wcout << "Error: Couldn't open process" << std::endl;
|
||||
break;
|
||||
case 2:
|
||||
std::wcout << "Error: Couldn't allocate memory" << std::endl;
|
||||
break;
|
||||
case 3:
|
||||
std::wcout << "Error: Couldn't write memory" << std::endl;
|
||||
break;
|
||||
case 4:
|
||||
std::wcout << "Error: Couldn't get pointer ro LoadLibraryW" << std::endl;
|
||||
break;
|
||||
case 5:
|
||||
std::wcout << "Error: Couldn't start remote thread" << std::endl;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (std::wstring(argv[1]).find(L"--eject") != std::wstring::npos)
|
||||
{
|
||||
int result = Injector::Eject(pid, libPath);
|
||||
switch (result)
|
||||
{
|
||||
case 0:
|
||||
std::wcout << "Eject success!" << std::endl;
|
||||
break;
|
||||
case 1:
|
||||
std::wcout << "Error: Couldn't open process" << std::endl;
|
||||
break;
|
||||
case 2:
|
||||
std::wcout << "Error: Couldn't find module in process" << std::endl;
|
||||
break;
|
||||
case 3:
|
||||
std::wcout << "Error: Couldn't get pointer ro FreeLibrary" << std::endl;
|
||||
break;
|
||||
case 4:
|
||||
std::wcout << "Error: Couldn't start remote thread" << std::endl;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
@ -0,0 +1,75 @@
|
||||
/*
|
||||
Copyright 2018 Peter Repukat - FlatspotSoftware
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
#pragma once
|
||||
#include <Windows.h>
|
||||
|
||||
class SteamTarget;
|
||||
|
||||
namespace overlay_hook
|
||||
{
|
||||
DWORD JMPBackOpen;
|
||||
DWORD JMPBackClosed;
|
||||
|
||||
TargetOverlay* target_overlay;
|
||||
|
||||
|
||||
__declspec(naked) void overlay_opend_hookFN()
|
||||
{
|
||||
|
||||
|
||||
//excute overrriden instructions
|
||||
__asm {
|
||||
push esi
|
||||
mov byte ptr ds : [esi + 0x28], 1
|
||||
}
|
||||
|
||||
//our hook code...
|
||||
target_overlay->onOverlayOpened();
|
||||
|
||||
|
||||
|
||||
//std::cout << "Opened!\n";
|
||||
|
||||
|
||||
//jump back
|
||||
__asm
|
||||
{
|
||||
jmp[JMPBackOpen] //jump back and continiue with original steam function
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
__declspec(naked) void overlay_closed_hookFN()
|
||||
{
|
||||
//excute overrriden instructions
|
||||
__asm {
|
||||
mov dword ptr ds : [esi + 0x24], 0
|
||||
mov byte ptr ds : [esi + 0x28], 0
|
||||
}
|
||||
|
||||
//our hook code...
|
||||
target_overlay->onOverlayClosed();
|
||||
|
||||
//std::cout << "Closed!\n";
|
||||
|
||||
//jump back
|
||||
__asm
|
||||
{
|
||||
jmp[JMPBackClosed] //jump back and continiue with original steam function
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,107 @@
|
||||
/*
|
||||
Copyright 2018 Peter Repukat - FlatspotSoftware
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
/*
|
||||
|
||||
SteamTarget - Does most of GloSCs heavy lifting.
|
||||
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#include "TargetOverlay.h"
|
||||
#include "VirtualControllerThread.h"
|
||||
|
||||
#include <QApplication>
|
||||
#include <QTimer>
|
||||
#include <QSystemTrayIcon>
|
||||
#include <QMenu>
|
||||
|
||||
#include <functional>
|
||||
|
||||
#include <Windows.h>
|
||||
#include <dwmapi.h>
|
||||
|
||||
|
||||
|
||||
class SteamTarget : public QApplication
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
SteamTarget(int& argc, char** argv);
|
||||
SteamTarget(const SteamTarget& other) = delete;
|
||||
SteamTarget(SteamTarget&& other) noexcept = delete;
|
||||
SteamTarget& operator=(const SteamTarget& other) = delete;
|
||||
SteamTarget& operator=(SteamTarget&& other) noexcept = delete;
|
||||
~SteamTarget() = default;
|
||||
|
||||
void init();
|
||||
static BOOL WINAPI ConsoleCtrlCallback(DWORD dwCtrlType);
|
||||
|
||||
public slots:
|
||||
void onAboutToQuit();
|
||||
|
||||
|
||||
private:
|
||||
void readIni();
|
||||
void initOverlayEvents();
|
||||
|
||||
void launchWatchdog() const;
|
||||
void launchApplication();
|
||||
|
||||
static HRESULT LaunchUWPApp(LPCWSTR packageFullName, PDWORD pdwProcessId);
|
||||
|
||||
TargetOverlay target_overlay_;
|
||||
std::unique_ptr<VirtualControllerThread> controller_thread_;
|
||||
|
||||
//Settings from .ini file
|
||||
bool hook_steam_ = true;
|
||||
bool enable_overlay_ = true;
|
||||
bool enable_overlay_only_config_ = false;
|
||||
bool enable_controllers_ = true;
|
||||
bool use_desktop_conf_ = false;
|
||||
bool launch_game_ = false;
|
||||
bool close_launched_done_ = false;
|
||||
bool launch_uwp_ = false;
|
||||
std::string launch_app_path_ = "";
|
||||
std::string launch_app_args_ = "";
|
||||
int update_rate_ = 5000;
|
||||
|
||||
QTimer launch_check_timer_;
|
||||
|
||||
QSystemTrayIcon sys_tray_icon_;
|
||||
QMenu tray_icon_menu_;
|
||||
|
||||
|
||||
//Hooking stuff...
|
||||
#ifdef _AMD64_
|
||||
constexpr static const char* overlay_module_name = "GameOverlayRenderer64.dll";
|
||||
constexpr static const char* overlay_open_func_sig = "TODO";
|
||||
constexpr static const char* overlay_open_func_mask= "TODO";
|
||||
#else
|
||||
constexpr static const char* overlay_module_name = "GameOverlayRenderer.dll";
|
||||
|
||||
constexpr static const char* overlay_open_func_sig = "\x56\xC6\x46\x28\x01";
|
||||
constexpr static const char* overlay_open_func_mask = "xxxxx";
|
||||
|
||||
constexpr static const char* overlay_closed_func_sig = "\xC7\x46\x24\x00\x00\x00\x00\xC6\x46\x28\x00";
|
||||
constexpr static const char* overlay_closed_func_mask = "xxxxxxxxxxx";
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
};
|
||||
|
Binary file not shown.
@ -1,543 +0,0 @@
|
||||
/*
|
||||
Copyright 2016 Peter Repukat - FlatspotSoftware
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
#include "SteamTargetRenderer.h"
|
||||
|
||||
std::atomic<bool> SteamTargetRenderer::overlayOpen = false;
|
||||
HHOOK SteamTargetRenderer::hook = nullptr;
|
||||
std::atomic<bool> SteamTargetRenderer::bHookSteam = false;
|
||||
|
||||
|
||||
SteamTargetRenderer::SteamTargetRenderer(int& argc, char** argv) : QApplication(argc, argv)
|
||||
{
|
||||
getSteamOverlay();
|
||||
loadLogo();
|
||||
|
||||
SetConsoleCtrlHandler(reinterpret_cast<PHANDLER_ROUTINE>(ConsoleCtrlCallback), true);
|
||||
if (this->arguments().size() == 1)
|
||||
{
|
||||
std::cerr << "Target configuration file must be specified!" << std::endl;
|
||||
MessageBoxW(NULL, L"Target configuration file must be specified!", L"GloSC-SteamTarget", MB_OK);
|
||||
|
||||
QTimer::singleShot(0, this, []()
|
||||
{
|
||||
QApplication::exit(1);
|
||||
}); //call after ctor
|
||||
|
||||
} else {
|
||||
QSettings settings(this->arguments().at(1), QSettings::IniFormat);
|
||||
settings.beginGroup("BaseConf");
|
||||
const QStringList childKeys = settings.childKeys();
|
||||
for (auto &childkey : childKeys)
|
||||
{
|
||||
if (childkey == "bDrawDebugEdges")
|
||||
{
|
||||
bDrawDebugEdges = settings.value(childkey).toBool();
|
||||
}
|
||||
else if (childkey == "bEnableOverlay") {
|
||||
bDrawOverlay = settings.value(childkey).toBool();
|
||||
}
|
||||
else if (childkey == "bEnableControllers") {
|
||||
bEnableControllers = settings.value(childkey).toBool();
|
||||
}
|
||||
else if (childkey == "bHookSteam") {
|
||||
bHookSteam = settings.value(childkey).toBool();
|
||||
}
|
||||
else if (childkey == "bUseDesktopConfig") {
|
||||
bUseDesktopConfig = settings.value(childkey).toBool();
|
||||
}
|
||||
}
|
||||
settings.endGroup();
|
||||
|
||||
#ifndef NDEBUG
|
||||
bDrawDebugEdges = true;
|
||||
#endif // NDEBUG
|
||||
sfCshape = sf::CircleShape(100.f);
|
||||
sfCshape.setFillColor(sf::Color(128, 128, 128, 128));
|
||||
sfCshape.setOrigin(sf::Vector2f(100, 100));
|
||||
sf::VideoMode mode = sf::VideoMode::getDesktopMode();
|
||||
sfWindow.create(sf::VideoMode(mode.width - 16, mode.height - 32), "GloSC_OverlayWindow"); //Window is too large ; always 16 and 32 pixels? - sf::Style::None breaks transparency!
|
||||
sfWindow.setFramerateLimit(iRefreshRate);
|
||||
sfWindow.setPosition(sf::Vector2i(0, 0));
|
||||
makeSfWindowTransparent(sfWindow);
|
||||
|
||||
sfWindow.setActive(false);
|
||||
consoleHwnd = GetConsoleWindow(); //We need a console for a dirty hack to make sure we stay in game bindings
|
||||
//QT Windows cause trouble with the overlay, so we cannot use them
|
||||
#ifdef NDEBUG
|
||||
ShowWindow(consoleHwnd, SW_HIDE);
|
||||
#endif // NDEBUG
|
||||
|
||||
|
||||
if (bEnableControllers)
|
||||
controllerThread.run();
|
||||
|
||||
QTimer::singleShot(2000, this, &SteamTargetRenderer::launchApp); // lets steam do its thing
|
||||
|
||||
if (hmodGameOverlayRenderer != nullptr)
|
||||
{
|
||||
//Hook MessageQueue to detect if overlay gets opened / closed
|
||||
//Steam Posts a Message with 0x14FA / 0x14F7 when the overlay gets opened / closed
|
||||
hook = SetWindowsHookEx(WH_GETMESSAGE, HookCallback, nullptr, GetCurrentThreadId());
|
||||
}
|
||||
|
||||
|
||||
if (bUseDesktopConfig)
|
||||
{
|
||||
bHookSteam = false;
|
||||
QTimer::singleShot(1000, this, []()
|
||||
{
|
||||
HWND taskbar = FindWindow(L"Shell_TrayWnd", nullptr);
|
||||
SetFocus(taskbar);
|
||||
SetForegroundWindow(taskbar);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
SteamTargetRenderer::~SteamTargetRenderer()
|
||||
{
|
||||
|
||||
if (hmodGameOverlayRenderer != nullptr)
|
||||
{
|
||||
UnhookWindowsHookEx(hook);
|
||||
}
|
||||
|
||||
renderThread.join();
|
||||
if (controllerThread.isRunning())
|
||||
controllerThread.stop();
|
||||
}
|
||||
|
||||
void SteamTargetRenderer::run()
|
||||
{
|
||||
renderThread = std::thread(&SteamTargetRenderer::RunSfWindowLoop, this);
|
||||
}
|
||||
|
||||
void SteamTargetRenderer::stop()
|
||||
{
|
||||
bRunLoop = false;
|
||||
unhookBindings();
|
||||
QApplication::exit(0);
|
||||
}
|
||||
|
||||
|
||||
void SteamTargetRenderer::RunSfWindowLoop()
|
||||
{
|
||||
if (!bRunLoop)
|
||||
return;
|
||||
sfWindow.setActive(true);
|
||||
|
||||
bool hasJustLaunched = true;
|
||||
|
||||
if (bDrawOverlay)
|
||||
SetWindowPos(sfWindow.getSystemHandle(), HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_ASYNCWINDOWPOS);
|
||||
else
|
||||
{
|
||||
ShowWindow(sfWindow.getSystemHandle(), SW_HIDE);
|
||||
sfWindow.setFramerateLimit(1); //Window is not shown anyway,
|
||||
ShowWindow(consoleHwnd, SW_SHOW); //Show the console window so the user sees SOMETHING
|
||||
}
|
||||
|
||||
|
||||
while (sfWindow.isOpen() && bRunLoop)
|
||||
{
|
||||
|
||||
sf::Event event;
|
||||
while (sfWindow.pollEvent(event))
|
||||
{
|
||||
if (event.type == sf::Event::Closed)
|
||||
sfWindow.close();
|
||||
}
|
||||
|
||||
sfWindow.clear(sf::Color::Transparent);
|
||||
|
||||
if (bDrawDebugEdges)
|
||||
drawDebugEdges();
|
||||
|
||||
//we inject and hook here to spare IPC and let the dll grab the steam appID of the launched process when the config switches (config switches w/ focus)
|
||||
if (hasJustLaunched)
|
||||
{
|
||||
if (bHookSteam)
|
||||
hookBindings(); //cleanup - unhooking / unloading of dll is managed by the GloSC gamelauncher rather than here
|
||||
hasJustLaunched = false;
|
||||
}
|
||||
|
||||
|
||||
//Window focus trickery
|
||||
if (hmodGameOverlayRenderer != nullptr)
|
||||
{
|
||||
if (overlayOpen)
|
||||
{
|
||||
if (!bNeedFocusSwitch)
|
||||
{
|
||||
bNeedFocusSwitch = true;
|
||||
|
||||
hwForeGroundWindow = GetForegroundWindow();
|
||||
|
||||
std::cout << "Saving current ForegorundWindow HWND: " << hwForeGroundWindow << std::endl;
|
||||
std::cout << "Activating OverlayWindow" << std::endl;
|
||||
|
||||
SetWindowLong(sfWindow.getSystemHandle(), GWL_EXSTYLE, WS_EX_LAYERED); //make overlay window clickable
|
||||
|
||||
//Actually activate the overlaywindow
|
||||
stealFocus(sfWindow.getSystemHandle());
|
||||
|
||||
//Move the mouse cursor inside the overlaywindow
|
||||
//this is neccessary because steam doesn't want to switch to big picture bindings if mouse isn't inside
|
||||
moveMouseIntoOverlay();
|
||||
}
|
||||
sfWindow.draw(backgroundSprite);
|
||||
} else {
|
||||
if (bNeedFocusSwitch)
|
||||
{
|
||||
std::cout << "Deactivating OverlayWindow" << std::endl;
|
||||
|
||||
//make overlaywindow clickthrough - WS_EX_TRANSPARENT - again
|
||||
SetWindowLong(sfWindow.getSystemHandle(), GWL_EXSTYLE, WS_EX_LAYERED | WS_EX_TRANSPARENT);
|
||||
|
||||
std::cout << "Switching to previously focused window" << std::endl;
|
||||
|
||||
//switch back the the previosly focused window
|
||||
stealFocus(hwForeGroundWindow);
|
||||
bNeedFocusSwitch = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
sfWindow.display();
|
||||
}
|
||||
stop();
|
||||
}
|
||||
|
||||
void SteamTargetRenderer::getSteamOverlay()
|
||||
{
|
||||
hmodGameOverlayRenderer = GetModuleHandle(overlayModuleName);
|
||||
|
||||
if (hmodGameOverlayRenderer != nullptr)
|
||||
{
|
||||
std::cout << overlayModuleName << " found; Module at: 0x" << hmodGameOverlayRenderer << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void SteamTargetRenderer::makeSfWindowTransparent(sf::RenderWindow & window)
|
||||
{
|
||||
HWND hwnd = window.getSystemHandle();
|
||||
SetWindowLong(hwnd, GWL_STYLE, WS_VISIBLE | WS_POPUP &~WS_CAPTION);
|
||||
SetWindowLong(hwnd, GWL_EXSTYLE, WS_EX_LAYERED | WS_EX_TRANSPARENT | WS_EX_TOPMOST);
|
||||
|
||||
MARGINS margins;
|
||||
margins.cxLeftWidth = -1;
|
||||
|
||||
DwmExtendFrameIntoClientArea(hwnd, &margins);
|
||||
SetWindowPos(hwnd, HWND_TOPMOST, 0, 0, 0, 0, SWP_FRAMECHANGED | SWP_NOMOVE | SWP_NOSIZE);
|
||||
|
||||
|
||||
window.clear(sf::Color::Transparent);
|
||||
window.display();
|
||||
}
|
||||
|
||||
void SteamTargetRenderer::drawDebugEdges()
|
||||
{
|
||||
sfCshape.setPosition(sf::Vector2f(-25, -25));
|
||||
sfWindow.draw(sfCshape);
|
||||
sfCshape.setPosition(sf::Vector2f(sfWindow.getSize().x + 25, -25));
|
||||
sfWindow.draw(sfCshape);
|
||||
sfCshape.setPosition(sf::Vector2f(-25, sfWindow.getSize().y));
|
||||
sfWindow.draw(sfCshape);
|
||||
sfCshape.setPosition(sf::Vector2f(sfWindow.getSize().x, sfWindow.getSize().y));
|
||||
sfWindow.draw(sfCshape);
|
||||
|
||||
}
|
||||
|
||||
void SteamTargetRenderer::hookBindings() const
|
||||
{
|
||||
std::cout << "Hooking Steam..." << std::endl;
|
||||
|
||||
QString dir = QDir::toNativeSeparators(QCoreApplication::applicationDirPath());
|
||||
dir = dir.mid(0, dir.lastIndexOf("\\"));
|
||||
|
||||
QProcess proc;
|
||||
proc.setNativeArguments(" --inject ");
|
||||
proc.setWorkingDirectory(dir);
|
||||
proc.start("./Injector.exe", QIODevice::ReadOnly);
|
||||
proc.waitForStarted();
|
||||
proc.waitForFinished();
|
||||
|
||||
if (QString::fromStdString(proc.readAll().toStdString()).contains("Inject success!")) //if we have injected (and patched the function)
|
||||
{
|
||||
std::cout << "Successfully hooked Steam!" << std::endl;
|
||||
|
||||
//tell the GloSC_GameLauncher that we have hooked steam
|
||||
//it will deal with checking if the target is still alive and unload the dll / unhook then
|
||||
// - ensures unloading / unhooking even if this process crashes or gets unexpectedly killed
|
||||
QSharedMemory sharedMemInstance("GloSC_GameLauncher");
|
||||
if (!sharedMemInstance.create(1024) && sharedMemInstance.error() == QSharedMemory::AlreadyExists)
|
||||
{
|
||||
QBuffer buffer;
|
||||
QDataStream dataStream(&buffer);
|
||||
QStringList stringList;
|
||||
|
||||
sharedMemInstance.attach();
|
||||
sharedMemInstance.lock();
|
||||
|
||||
buffer.setData(static_cast<const char*>(sharedMemInstance.constData()), sharedMemInstance.size());
|
||||
buffer.open(QBuffer::ReadOnly);
|
||||
dataStream >> stringList;
|
||||
buffer.close();
|
||||
|
||||
int i = stringList.indexOf(IsSteamHooked) + 1;
|
||||
stringList.replace(i, "1");
|
||||
|
||||
|
||||
buffer.open(QBuffer::ReadWrite);
|
||||
QDataStream out(&buffer);
|
||||
out << stringList;
|
||||
int size = buffer.size();
|
||||
char *to = static_cast<char*>(sharedMemInstance.data());
|
||||
const char *from = buffer.data().data();
|
||||
memcpy(to, from, qMin(sharedMemInstance.size(), size));
|
||||
buffer.close();
|
||||
|
||||
sharedMemInstance.unlock();
|
||||
sharedMemInstance.detach();
|
||||
}
|
||||
} else {
|
||||
std::cout << "Hooking Steam failed!" << std::endl;
|
||||
|
||||
MessageBoxW(NULL, L"Hooking Steam failed!", L"GloSC-SteamTarget", MB_OK);
|
||||
}
|
||||
}
|
||||
|
||||
void SteamTargetRenderer::loadLogo()
|
||||
{
|
||||
HRSRC rsrcData = FindResource(NULL, L"ICOPNG", RT_RCDATA);
|
||||
DWORD rsrcDataSize = SizeofResource(NULL, rsrcData);
|
||||
HGLOBAL grsrcData = LoadResource(NULL, rsrcData);
|
||||
LPVOID firstByte = LockResource(grsrcData);
|
||||
spriteTexture = std::make_unique<sf::Texture>();
|
||||
spriteTexture->loadFromMemory(firstByte, rsrcDataSize);
|
||||
backgroundSprite.setTexture(*spriteTexture);
|
||||
backgroundSprite.setOrigin(sf::Vector2f(spriteTexture->getSize().x / 2.f, spriteTexture->getSize().y / 2));
|
||||
sf::VideoMode winSize = sf::VideoMode::getDesktopMode();
|
||||
backgroundSprite.setPosition(sf::Vector2f(winSize.width / 2.f, winSize.height / 2.f));
|
||||
}
|
||||
|
||||
void SteamTargetRenderer::moveMouseIntoOverlay()
|
||||
{
|
||||
RECT rect = { 0 };
|
||||
if (GetWindowRect(sfWindow.getSystemHandle(), &rect))
|
||||
{
|
||||
POINT cursorPos = { 0 };
|
||||
GetCursorPos(&cursorPos);
|
||||
if (PtInRect(&rect, cursorPos))
|
||||
{
|
||||
SetCursorPos(cursorPos.x+1, cursorPos.y);
|
||||
}
|
||||
else
|
||||
{
|
||||
SetCursorPos(rect.left + 16, rect.top + 16);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
//WinHook Callback to check if the overlay is opened/closed
|
||||
LRESULT WINAPI SteamTargetRenderer::HookCallback(int nCode, WPARAM wParam, LPARAM lParam)
|
||||
{
|
||||
if (nCode >= 0)
|
||||
{
|
||||
PMSG msg = reinterpret_cast<PMSG>(lParam);
|
||||
std::cout << "DEBUG: " << "message: " << msg->message << std::endl;
|
||||
if (msg->message == 0x14FA || msg->message == 0x14FF) //Posted when the overlay gets opened
|
||||
{
|
||||
overlayOpen = true;
|
||||
std::cout << "Overlay Opened!\n";
|
||||
}
|
||||
else if (msg->message == 0x14F7 || msg->message == 0x14FD || msg->message == 512 || msg->message == 0x2a3)
|
||||
{
|
||||
overlayOpen = false;
|
||||
std::cout << "Overlay closed!\n";
|
||||
}
|
||||
}
|
||||
return CallNextHookEx(hook, nCode, wParam, lParam);
|
||||
}
|
||||
|
||||
void SteamTargetRenderer::unhookBindings()
|
||||
{
|
||||
if (bHookSteam)
|
||||
{
|
||||
QString dir = QDir::toNativeSeparators(QCoreApplication::applicationDirPath());
|
||||
dir = dir.mid(0, dir.lastIndexOf("\\"));
|
||||
|
||||
QProcess proc;
|
||||
proc.setNativeArguments(" --eject ");
|
||||
proc.setWorkingDirectory(dir);
|
||||
proc.start("./Injector.exe", QIODevice::ReadOnly);
|
||||
proc.waitForStarted();
|
||||
proc.waitForFinished();
|
||||
}
|
||||
}
|
||||
|
||||
BOOL SteamTargetRenderer::ConsoleCtrlCallback(DWORD dwCtrlType)
|
||||
{
|
||||
if (dwCtrlType == CTRL_CLOSE_EVENT || dwCtrlType == CTRL_BREAK_EVENT || dwCtrlType == CTRL_C_EVENT)
|
||||
{
|
||||
unhookBindings();
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void SteamTargetRenderer::stealFocus(HWND hwnd)
|
||||
{
|
||||
DWORD dwCurrentThread = GetCurrentThreadId();
|
||||
DWORD dwFGThread = GetWindowThreadProcessId(GetForegroundWindow(), nullptr);
|
||||
|
||||
AttachThreadInput(dwCurrentThread, dwFGThread, TRUE);
|
||||
|
||||
// Possible actions you may wan to bring the window into focus.
|
||||
SetForegroundWindow(hwnd);
|
||||
SetCapture(hwnd);
|
||||
SetFocus(hwnd);
|
||||
SetActiveWindow(hwnd);
|
||||
EnableWindow(hwnd, TRUE);
|
||||
|
||||
AttachThreadInput(dwCurrentThread, dwFGThread, FALSE);
|
||||
|
||||
|
||||
sf::Clock clock;
|
||||
while (!SetForegroundWindow(hwnd) && clock.getElapsedTime().asMilliseconds() < 1000) //try to forcefully set foreground window
|
||||
{
|
||||
Sleep(1);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void SteamTargetRenderer::launchApp()
|
||||
{
|
||||
SetPriorityClass(GetCurrentProcess(), HIGH_PRIORITY_CLASS);
|
||||
|
||||
bool launchGame = false;
|
||||
bool closeWhenDone = false;
|
||||
QString type = "Win32";
|
||||
QString path = "";
|
||||
QString args;
|
||||
QSettings settings(this->arguments().at(1), QSettings::IniFormat);
|
||||
settings.beginGroup("LaunchGame");
|
||||
const QStringList childKeys = settings.childKeys();
|
||||
for (auto &childkey : childKeys)
|
||||
{
|
||||
if (childkey == "bLaunchGame")
|
||||
launchGame = settings.value(childkey).toBool();
|
||||
else if (childkey == "Type")
|
||||
type = settings.value(childkey).toString();
|
||||
else if (childkey == "Path")
|
||||
path = settings.value(childkey).toString();
|
||||
else if (childkey == "Args")
|
||||
args = settings.value(childkey).toString();
|
||||
else if (childkey == "bCloseWhenDone")
|
||||
closeWhenDone = settings.value("bCloseWhenDone").toBool();
|
||||
}
|
||||
settings.endGroup();
|
||||
|
||||
if (launchGame)
|
||||
{
|
||||
QSharedMemory sharedMemInstance("GloSC_GameLauncher");
|
||||
if (!sharedMemInstance.create(1024) && sharedMemInstance.error() == QSharedMemory::AlreadyExists)
|
||||
{
|
||||
|
||||
if (type == "UWP")
|
||||
{
|
||||
HWND hwnd = sfWindow.getSystemHandle();
|
||||
SetWindowPos(hwnd, HWND_BOTTOM, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_ASYNCWINDOWPOS);
|
||||
QTimer::singleShot(5000, [hwnd]()
|
||||
{
|
||||
SetWindowPos(hwnd, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_ASYNCWINDOWPOS);
|
||||
});
|
||||
}
|
||||
|
||||
QBuffer buffer;
|
||||
QDataStream dataStream(&buffer);
|
||||
QStringList stringList;
|
||||
|
||||
sharedMemInstance.attach();
|
||||
sharedMemInstance.lock();
|
||||
|
||||
buffer.setData(static_cast<const char*>(sharedMemInstance.constData()), sharedMemInstance.size());
|
||||
buffer.open(QBuffer::ReadOnly);
|
||||
dataStream >> stringList;
|
||||
buffer.close();
|
||||
|
||||
|
||||
|
||||
int lgt_index = stringList.indexOf(LaunchGame);
|
||||
stringList.replace(lgt_index + 1, type);
|
||||
stringList.replace(lgt_index + 2, path);
|
||||
stringList.replace(lgt_index + 3, args);
|
||||
|
||||
|
||||
buffer.open(QBuffer::ReadWrite);
|
||||
QDataStream out(&buffer);
|
||||
out << stringList;
|
||||
int size = buffer.size();
|
||||
char *to = static_cast<char*>(sharedMemInstance.data());
|
||||
const char *from = buffer.data().data();
|
||||
memcpy(to, from, qMin(sharedMemInstance.size(), size));
|
||||
buffer.close();
|
||||
|
||||
sharedMemInstance.unlock();
|
||||
sharedMemInstance.detach();
|
||||
|
||||
if (closeWhenDone)
|
||||
{
|
||||
updateTimer.setInterval(1111);
|
||||
connect(&updateTimer, SIGNAL(timeout()), this, SLOT(checkSharedMem()));
|
||||
updateTimer.start();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void SteamTargetRenderer::checkSharedMem()
|
||||
{
|
||||
QSharedMemory sharedMemInstance("GloSC_GameLauncher");
|
||||
if (!sharedMemInstance.create(1024) && sharedMemInstance.error() == QSharedMemory::AlreadyExists)
|
||||
{
|
||||
QBuffer buffer;
|
||||
QDataStream in(&buffer);
|
||||
QStringList stringList;
|
||||
|
||||
sharedMemInstance.attach();
|
||||
sharedMemInstance.lock();
|
||||
buffer.setData(static_cast<const char*>(sharedMemInstance.constData()), sharedMemInstance.size());
|
||||
buffer.open(QBuffer::ReadOnly);
|
||||
in >> stringList;
|
||||
buffer.close();
|
||||
sharedMemInstance.unlock();
|
||||
sharedMemInstance.detach();
|
||||
|
||||
int close_index = stringList.indexOf(LaunchedProcessFinished) + 1;
|
||||
|
||||
if (close_index > 0 && stringList.at(close_index).toInt() == 1)
|
||||
bRunLoop = false;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
@ -1,128 +0,0 @@
|
||||
/*
|
||||
Copyright 2016 Peter Repukat - FlatspotSoftware
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include <Windows.h>
|
||||
#include <dwmapi.h>
|
||||
|
||||
#include <SFML\System.hpp>
|
||||
#include <SFML\Graphics.hpp>
|
||||
|
||||
#include <iostream>
|
||||
#include <thread>
|
||||
|
||||
#include <QApplication>
|
||||
#include <QTimer>
|
||||
#include <QProcess>
|
||||
#include <QBuffer>
|
||||
#include <QDatastream>
|
||||
#include <QSharedmemory>
|
||||
#include <QSettings>
|
||||
#include <QCoreApplication>
|
||||
#include <QDir>
|
||||
#include <psapi.h>
|
||||
|
||||
#include "VirtualControllerThread.h"
|
||||
#include <atomic>
|
||||
|
||||
class SteamTargetRenderer : public QApplication
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
SteamTargetRenderer(int& argc, char** argv);
|
||||
~SteamTargetRenderer();
|
||||
|
||||
void run();
|
||||
|
||||
|
||||
|
||||
|
||||
private:
|
||||
void stop();
|
||||
void getSteamOverlay();
|
||||
void RunSfWindowLoop();
|
||||
static void makeSfWindowTransparent(sf::RenderWindow& window);
|
||||
void drawDebugEdges();
|
||||
void hookBindings() const;
|
||||
|
||||
void loadLogo();
|
||||
|
||||
void moveMouseIntoOverlay();
|
||||
|
||||
static LRESULT WINAPI HookCallback(int nCode, WPARAM wParam, LPARAM lParam);
|
||||
|
||||
static void unhookBindings();
|
||||
|
||||
static BOOL WINAPI ConsoleCtrlCallback(_In_ DWORD dwCtrlType);
|
||||
|
||||
static void stealFocus(HWND hwnd);
|
||||
|
||||
std::atomic<bool> bRunLoop = true;
|
||||
|
||||
bool bUseDesktopConfig = false;
|
||||
bool bDrawDebugEdges = false;
|
||||
bool bDrawOverlay = true;
|
||||
bool bVsync = false;
|
||||
int iRefreshRate = 30;
|
||||
sf::CircleShape sfCshape;
|
||||
sf::RenderWindow sfWindow;
|
||||
|
||||
std::thread renderThread;
|
||||
|
||||
HWND consoleHwnd;
|
||||
|
||||
HMODULE hmodGameOverlayRenderer = nullptr;
|
||||
#ifdef _AMD64_
|
||||
WCHAR* overlayModuleName = L"GameOverlayRenderer64.dll";
|
||||
#else
|
||||
WCHAR* overlayModuleName = L"GameOverlayRenderer.dll";
|
||||
#endif
|
||||
static std::atomic<bool> overlayOpen;
|
||||
static HHOOK hook;
|
||||
|
||||
|
||||
HWND hwForeGroundWindow = nullptr;
|
||||
bool bNeedFocusSwitch = false;
|
||||
|
||||
VirtualControllerThread controllerThread;
|
||||
|
||||
bool bEnableControllers = true;
|
||||
|
||||
static std::atomic<bool> bHookSteam;
|
||||
|
||||
QTimer updateTimer;
|
||||
|
||||
std::unique_ptr<sf::Texture> spriteTexture;
|
||||
sf::Sprite backgroundSprite;
|
||||
|
||||
const QString LaunchGame = "LaunchGame";
|
||||
const QString LaunchedProcessFinished = "LaunchedProcessFinished";
|
||||
const QString IsSteamHooked = "IsSteamHooked";
|
||||
const QStringList defaultSharedMemData = QStringList()
|
||||
<< LaunchGame
|
||||
<< ""
|
||||
<< ""
|
||||
<< LaunchedProcessFinished
|
||||
<< "0"
|
||||
<< IsSteamHooked
|
||||
<< "-1";
|
||||
|
||||
private slots:
|
||||
void launchApp();
|
||||
void checkSharedMem();
|
||||
};
|
||||
|
@ -0,0 +1,268 @@
|
||||
/*
|
||||
Copyright 2018 Peter Repukat - FlatspotSoftware
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
#include "Injector.h"
|
||||
#include <tlhelp32.h>
|
||||
#include <iostream>
|
||||
|
||||
#include "../common/loguru.hpp"
|
||||
|
||||
void Injector::TakeDebugPrivilege()
|
||||
{
|
||||
HANDLE hProcess = GetCurrentProcess(), hToken;
|
||||
TOKEN_PRIVILEGES priv;
|
||||
LUID luid = { NULL };
|
||||
|
||||
OpenProcessToken(hProcess, TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken);
|
||||
LookupPrivilegeValue(0, SE_DEBUG_NAME, &luid);
|
||||
|
||||
priv.PrivilegeCount = 1;
|
||||
priv.Privileges[0].Luid = luid;
|
||||
priv.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
|
||||
AdjustTokenPrivileges(hToken, false, &priv, sizeof(priv), NULL, NULL);
|
||||
|
||||
CloseHandle(hToken);
|
||||
CloseHandle(hProcess);
|
||||
}
|
||||
|
||||
int Injector::Inject(DWORD pid, std::wstring &libPath)
|
||||
{
|
||||
HANDLE hProcess = NULL, allocAddress = NULL, hRemoteThread = NULL;
|
||||
LPTHREAD_START_ROUTINE pfnThreadRtn = NULL;
|
||||
|
||||
size_t pathSize = (libPath.length() + 1) * sizeof(wchar_t);
|
||||
|
||||
hProcess = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_CREATE_THREAD | PROCESS_VM_OPERATION | PROCESS_VM_WRITE, false, pid);
|
||||
|
||||
if (!hProcess)
|
||||
{
|
||||
return 1;
|
||||
|
||||
}
|
||||
|
||||
allocAddress = VirtualAllocEx(hProcess, NULL, pathSize, MEM_COMMIT, PAGE_READWRITE);
|
||||
|
||||
if (!allocAddress)
|
||||
{
|
||||
CloseHandle(hProcess);
|
||||
return 2;
|
||||
}
|
||||
|
||||
if (!WriteProcessMemory(hProcess, (LPVOID)allocAddress, libPath.c_str(), pathSize, NULL))
|
||||
{
|
||||
VirtualFreeEx(hProcess, allocAddress, pathSize, MEM_DECOMMIT);
|
||||
CloseHandle(hProcess);
|
||||
return 3;
|
||||
}
|
||||
|
||||
pfnThreadRtn = reinterpret_cast<PTHREAD_START_ROUTINE>(GetProcAddress(GetModuleHandle(L"Kernel32"), "LoadLibraryW"));
|
||||
if (!pfnThreadRtn)
|
||||
{
|
||||
VirtualFreeEx(hProcess, allocAddress, pathSize, MEM_DECOMMIT);
|
||||
CloseHandle(hProcess);
|
||||
return 4;
|
||||
}
|
||||
|
||||
hRemoteThread = CreateRemoteThread(hProcess, NULL, 0, pfnThreadRtn, allocAddress, 0, NULL);
|
||||
|
||||
if (!hRemoteThread)
|
||||
{
|
||||
VirtualFreeEx(hProcess, allocAddress, pathSize, MEM_DECOMMIT);
|
||||
CloseHandle(hProcess);
|
||||
return 5;
|
||||
}
|
||||
|
||||
WaitForSingleObject(hRemoteThread, INFINITE);
|
||||
|
||||
CloseHandle(hRemoteThread);
|
||||
VirtualFreeEx(hProcess, allocAddress, pathSize, MEM_DECOMMIT);
|
||||
CloseHandle(hProcess);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int Injector::Eject(DWORD pid, std::wstring &libPath)
|
||||
{
|
||||
HANDLE hProcess = NULL, hRemoteThread = NULL;
|
||||
HMODULE hLibMod = NULL;
|
||||
LPTHREAD_START_ROUTINE pfnThreadRtn = NULL;
|
||||
|
||||
|
||||
if (!findModule(pid, libPath, hLibMod))
|
||||
{
|
||||
return 2;
|
||||
}
|
||||
hProcess = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_CREATE_THREAD | PROCESS_VM_OPERATION, false, pid);
|
||||
if (!hProcess)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
pfnThreadRtn = (PTHREAD_START_ROUTINE)GetProcAddress(GetModuleHandle(L"Kernel32"), "FreeLibrary");
|
||||
|
||||
if (!pfnThreadRtn)
|
||||
{
|
||||
CloseHandle(hProcess);
|
||||
return 3;
|
||||
}
|
||||
|
||||
hRemoteThread = CreateRemoteThread(hProcess, NULL, NULL, pfnThreadRtn, hLibMod, NULL, NULL);
|
||||
|
||||
if (!hRemoteThread)
|
||||
return 4;
|
||||
|
||||
WaitForSingleObject(hRemoteThread, INFINITE);
|
||||
|
||||
CloseHandle(hProcess);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool Injector::findModule(DWORD pid, std::wstring &libPath, HMODULE &hMod)
|
||||
{
|
||||
MODULEENTRY32W entry = { sizeof(entry) };
|
||||
HANDLE snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, pid);
|
||||
|
||||
if (Module32FirstW(snapshot, &entry) == TRUE)
|
||||
{
|
||||
while (Module32NextW(snapshot, &entry) == TRUE)
|
||||
{
|
||||
std::wstring ModuleName(entry.szModule);
|
||||
std::wstring ExePath(entry.szExePath);
|
||||
if (ModuleName == libPath || ExePath == libPath)
|
||||
{
|
||||
hMod = (HMODULE)entry.modBaseAddr;
|
||||
CloseHandle(snapshot);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
CloseHandle(snapshot);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int Injector::hookSteam()
|
||||
{
|
||||
Injector::TakeDebugPrivilege();
|
||||
|
||||
wchar_t wcPath[MAX_PATH];
|
||||
GetModuleFileName(GetModuleHandle(NULL), wcPath, MAX_PATH);
|
||||
std::wstring path(wcPath);
|
||||
std::wstring libPath = path.substr(0, 1 + path.find_last_of(L'\\')) + L"EnforceBindingDLL.dll";
|
||||
|
||||
DWORD pid = NULL;
|
||||
|
||||
PROCESSENTRY32 entry;
|
||||
entry.dwSize = sizeof(PROCESSENTRY32);
|
||||
HANDLE snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, NULL);
|
||||
if (Process32First(snapshot, &entry) == TRUE)
|
||||
{
|
||||
while (Process32Next(snapshot, &entry) == TRUE)
|
||||
{
|
||||
if (_wcsicmp(entry.szExeFile, L"steam.exe") == 0)
|
||||
{
|
||||
pid = entry.th32ProcessID;
|
||||
}
|
||||
}
|
||||
}
|
||||
CloseHandle(snapshot);
|
||||
|
||||
if (pid == NULL)
|
||||
{
|
||||
LOG_F(WARNING, "Can't detect Steam.exe running");
|
||||
return 0;
|
||||
}
|
||||
const int result = Injector::Inject(pid, libPath);
|
||||
switch (result)
|
||||
{
|
||||
case 0:
|
||||
LOG_F(INFO, "Inject success!");
|
||||
return 1;
|
||||
case 1:
|
||||
LOG_F(ERROR, "Couldn't open process");
|
||||
break;
|
||||
case 2:
|
||||
LOG_F(ERROR, "Couldn't allocate memory");
|
||||
break;
|
||||
case 3:
|
||||
LOG_F(ERROR, "Couldn't write memory");
|
||||
break;
|
||||
case 4:
|
||||
LOG_F(ERROR, "Couldn't get pointer ro LoadLibraryW");
|
||||
break;
|
||||
case 5:
|
||||
LOG_F(ERROR, "Couldn't start remote thread");
|
||||
break;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
int Injector::unhookSteam()
|
||||
{
|
||||
Injector::TakeDebugPrivilege();
|
||||
|
||||
wchar_t wcPath[MAX_PATH];
|
||||
GetModuleFileName(GetModuleHandle(NULL), wcPath, MAX_PATH);
|
||||
std::wstring path(wcPath);
|
||||
std::wstring libPath = path.substr(0, 1 + path.find_last_of(L'\\')) + L"EnforceBindingDLL.dll";
|
||||
|
||||
DWORD pid = NULL;
|
||||
|
||||
PROCESSENTRY32 entry;
|
||||
entry.dwSize = sizeof(PROCESSENTRY32);
|
||||
const HANDLE snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, NULL);
|
||||
if (Process32First(snapshot, &entry) == TRUE)
|
||||
{
|
||||
while (Process32Next(snapshot, &entry) == TRUE)
|
||||
{
|
||||
if (_wcsicmp(entry.szExeFile, L"steam.exe") == 0)
|
||||
{
|
||||
pid = entry.th32ProcessID;
|
||||
}
|
||||
}
|
||||
}
|
||||
CloseHandle(snapshot);
|
||||
|
||||
if (pid == NULL)
|
||||
{
|
||||
LOG_F(WARNING, "Can't detect Steam.exe running");
|
||||
return 0;
|
||||
}
|
||||
|
||||
const int result = Injector::Eject(pid, libPath);
|
||||
switch (result)
|
||||
{
|
||||
case 0:
|
||||
LOG_F(INFO, "Eject success!");
|
||||
return 1;
|
||||
case 1:
|
||||
LOG_F(ERROR, "Couldn't open process");
|
||||
break;
|
||||
case 2:
|
||||
LOG_F(ERROR, "Couldn't find module in process");
|
||||
break;
|
||||
case 3:
|
||||
LOG_F(ERROR, "Couldn't get pointer ro FreeLibrary");
|
||||
break;
|
||||
case 4:
|
||||
LOG_F(ERROR, "Couldn't start remote thread");
|
||||
break;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,89 @@
|
||||
/*
|
||||
Copyright 2018 Peter Repukat - FlatspotSoftware
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include <Windows.h>
|
||||
#include <Psapi.h>
|
||||
|
||||
namespace hook_commons
|
||||
{
|
||||
|
||||
//places a jmp instruction to a __declspec(naked) function on a given adress
|
||||
//nops the rest of bytes to don't break any instructions
|
||||
//part of patched code may has to be executed in the hook function
|
||||
void PlaceJMP(BYTE * Address, DWORD jumpTo, DWORD lenght)
|
||||
{
|
||||
DWORD dwOldProtect, dwBkup, dwReloadAddr;
|
||||
VirtualProtect(Address, lenght, PAGE_EXECUTE_READWRITE, &dwOldProtect);
|
||||
dwReloadAddr = (jumpTo - (DWORD)Address) - 5; //5 == lenght of jump instruction (1byte + 4byte address)
|
||||
*Address = 0xE9; //jmp instrcution
|
||||
*((DWORD*)(Address + 0x1)) = dwReloadAddr;
|
||||
|
||||
for (DWORD x = 5; x < lenght; x++)
|
||||
*(Address + x) = 0x90; //nop the rest
|
||||
|
||||
VirtualProtect(Address, lenght, dwOldProtect, &dwBkup);
|
||||
}
|
||||
|
||||
void RestoreBytes(BYTE * Address, BYTE * original, DWORD lenght)
|
||||
{
|
||||
DWORD dwOldProtect, dwBkup, dwReloadAddr;
|
||||
VirtualProtect(Address, lenght, PAGE_EXECUTE_READWRITE, &dwOldProtect);
|
||||
|
||||
|
||||
for (DWORD x = 0; x < lenght; x++)
|
||||
{
|
||||
*(Address + x) = *(original + x);
|
||||
}
|
||||
|
||||
VirtualProtect(Address, lenght, dwOldProtect, &dwBkup);
|
||||
}
|
||||
|
||||
MODULEINFO GetModInfo(const char * szModule)
|
||||
{
|
||||
MODULEINFO ret = { NULL };
|
||||
HMODULE mod = GetModuleHandleA(szModule);
|
||||
|
||||
if (mod != 0)
|
||||
GetModuleInformation(GetCurrentProcess(), mod, &ret, sizeof(MODULEINFO));
|
||||
return ret;
|
||||
}
|
||||
|
||||
//returns memory address of given pattern ind given module
|
||||
DWORD FindPattern(const char * module, const char * pattern, const char * mask)
|
||||
{
|
||||
MODULEINFO mInfo = GetModInfo(module);
|
||||
DWORD baseAddr = (DWORD)mInfo.lpBaseOfDll;
|
||||
if (baseAddr == 0)
|
||||
return NULL;
|
||||
DWORD size = mInfo.SizeOfImage;
|
||||
|
||||
DWORD patLenght = strlen(mask);
|
||||
|
||||
for (DWORD i = 0; i < size - patLenght; i++) //bad for loop btw...
|
||||
{
|
||||
bool found = true;
|
||||
for (DWORD j = 0; j < patLenght; j++)
|
||||
found &= mask[j] == '?' || pattern[j] == *(char*)(baseAddr + j + i);
|
||||
|
||||
if (found)
|
||||
return baseAddr + i;
|
||||
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
}
|
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,38 @@
|
||||
#pragma once
|
||||
#include <Windows.h>
|
||||
#include <tlhelp32.h>
|
||||
|
||||
namespace process_alive
|
||||
{
|
||||
//stolen from: https://stackoverflow.com/questions/1591342/c-how-to-determine-if-a-windows-process-is-running
|
||||
inline bool IsProcessRunning(const wchar_t *processName)
|
||||
{
|
||||
bool exists = false;
|
||||
PROCESSENTRY32 entry;
|
||||
entry.dwSize = sizeof(PROCESSENTRY32);
|
||||
|
||||
const HANDLE snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, NULL);
|
||||
|
||||
if (Process32First(snapshot, &entry))
|
||||
do {
|
||||
if (!_wcsicmp(entry.szExeFile, processName))
|
||||
{
|
||||
exists = true;
|
||||
break;
|
||||
}
|
||||
} while (Process32Next(snapshot, &entry));
|
||||
|
||||
CloseHandle(snapshot);
|
||||
return exists;
|
||||
}
|
||||
|
||||
inline BOOL IsProcessRunning(DWORD pid)
|
||||
{
|
||||
const HANDLE process = OpenProcess(SYNCHRONIZE, FALSE, pid);
|
||||
if (process == nullptr)
|
||||
return false;
|
||||
const DWORD ret = WaitForSingleObject(process, 0);
|
||||
CloseHandle(process);
|
||||
return ret == WAIT_TIMEOUT;
|
||||
}
|
||||
}
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -0,0 +1,126 @@
|
||||
|
||||
LICENSE ISSUES
|
||||
==============
|
||||
|
||||
The OpenSSL toolkit stays under a dual license, i.e. both the conditions of
|
||||
the OpenSSL License and the original SSLeay license apply to the toolkit.
|
||||
See below for the actual license texts. Actually both licenses are BSD-style
|
||||
Open Source licenses. In case of any license issues related to OpenSSL
|
||||
please contact openssl-core@openssl.org.
|
||||
|
||||
OpenSSL License
|
||||
---------------
|
||||
|
||||
/* ====================================================================
|
||||
* Copyright (c) 1998-2016 The OpenSSL Project. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
*
|
||||
* 3. All advertising materials mentioning features or use of this
|
||||
* software must display the following acknowledgment:
|
||||
* "This product includes software developed by the OpenSSL Project
|
||||
* for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
|
||||
*
|
||||
* 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
|
||||
* endorse or promote products derived from this software without
|
||||
* prior written permission. For written permission, please contact
|
||||
* openssl-core@openssl.org.
|
||||
*
|
||||
* 5. Products derived from this software may not be called "OpenSSL"
|
||||
* nor may "OpenSSL" appear in their names without prior written
|
||||
* permission of the OpenSSL Project.
|
||||
*
|
||||
* 6. Redistributions of any form whatsoever must retain the following
|
||||
* acknowledgment:
|
||||
* "This product includes software developed by the OpenSSL Project
|
||||
* for use in the OpenSSL Toolkit (http://www.openssl.org/)"
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
|
||||
* EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
|
||||
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
||||
* OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
* ====================================================================
|
||||
*
|
||||
* This product includes cryptographic software written by Eric Young
|
||||
* (eay@cryptsoft.com). This product includes software written by Tim
|
||||
* Hudson (tjh@cryptsoft.com).
|
||||
*
|
||||
*/
|
||||
|
||||
Original SSLeay License
|
||||
-----------------------
|
||||
|
||||
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
|
||||
* All rights reserved.
|
||||
*
|
||||
* This package is an SSL implementation written
|
||||
* by Eric Young (eay@cryptsoft.com).
|
||||
* The implementation was written so as to conform with Netscapes SSL.
|
||||
*
|
||||
* This library is free for commercial and non-commercial use as long as
|
||||
* the following conditions are aheared to. The following conditions
|
||||
* apply to all code found in this distribution, be it the RC4, RSA,
|
||||
* lhash, DES, etc., code; not just the SSL code. The SSL documentation
|
||||
* included with this distribution is covered by the same copyright terms
|
||||
* except that the holder is Tim Hudson (tjh@cryptsoft.com).
|
||||
*
|
||||
* Copyright remains Eric Young's, and as such any Copyright notices in
|
||||
* the code are not to be removed.
|
||||
* If this package is used in a product, Eric Young should be given attribution
|
||||
* as the author of the parts of the library used.
|
||||
* This can be in the form of a textual message at program startup or
|
||||
* in documentation (online or textual) provided with the package.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* "This product includes cryptographic software written by
|
||||
* Eric Young (eay@cryptsoft.com)"
|
||||
* The word 'cryptographic' can be left out if the rouines from the library
|
||||
* being used are not cryptographic related :-).
|
||||
* 4. If you include any Windows specific code (or a derivative thereof) from
|
||||
* the apps directory (application code) you must include an acknowledgement:
|
||||
* "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* The licence and distribution terms for any publically available version or
|
||||
* derivative of this code cannot be changed. i.e. this code cannot simply be
|
||||
* copied and put under another distribution licence
|
||||
* [including the GNU Public Licence.]
|
||||
*/
|
Binary file not shown.
Binary file not shown.
Loading…
Reference in New Issue