Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
8a7c463c52 | ||
|
|
eab77fba7a | ||
|
|
61d90a5a88 | ||
|
|
ef99f02bc7 | ||
|
|
9166a604d6 | ||
|
|
d5a1189053 | ||
|
|
cb52a53922 | ||
|
|
1aff2ff0c3 | ||
|
|
fd63aad3b8 | ||
|
|
9a807a0685 | ||
|
|
40fc9fa26f | ||
|
|
cf0d29d452 | ||
|
|
e411c207ae | ||
|
|
5df2704ccc | ||
|
|
36f468a599 | ||
|
|
dfae69834a | ||
|
|
e53b32fa57 | ||
|
|
969afac696 | ||
|
|
50d4f267ba | ||
|
|
33b9caaca9 | ||
|
|
4f84843b00 | ||
|
|
44f415f94d |
+4
-1
@@ -9,4 +9,7 @@
|
|||||||
url = https://github.com/gabomdq/SDL_GameControllerDB.git
|
url = https://github.com/gabomdq/SDL_GameControllerDB.git
|
||||||
[submodule "soundio/libsoundio"]
|
[submodule "soundio/libsoundio"]
|
||||||
path = soundio/libsoundio
|
path = soundio/libsoundio
|
||||||
url = https://github.com/andrewrk/libsoundio.git
|
url = https://github.com/cgutman/libsoundio.git
|
||||||
|
[submodule "h264bitstream/h264bitstream"]
|
||||||
|
path = h264bitstream/h264bitstream
|
||||||
|
url = https://github.com/aizvorski/h264bitstream.git
|
||||||
|
|||||||
@@ -0,0 +1,23 @@
|
|||||||
|
QT -= core gui
|
||||||
|
|
||||||
|
TARGET = AntiHooking
|
||||||
|
TEMPLATE = lib
|
||||||
|
|
||||||
|
# Support debug and release builds from command line for CI
|
||||||
|
CONFIG += debug_and_release
|
||||||
|
|
||||||
|
# Ensure symbols are always generated
|
||||||
|
CONFIG += force_debug_info
|
||||||
|
|
||||||
|
INCLUDEPATH += $$PWD/../libs/windows/include
|
||||||
|
contains(QT_ARCH, i386) {
|
||||||
|
LIBS += -L$$PWD/../libs/windows/lib/x86
|
||||||
|
}
|
||||||
|
contains(QT_ARCH, x86_64) {
|
||||||
|
LIBS += -L$$PWD/../libs/windows/lib/x64
|
||||||
|
}
|
||||||
|
|
||||||
|
LIBS += -lNktHookLib
|
||||||
|
DEFINES += ANTIHOOKING_LIBRARY
|
||||||
|
SOURCES += antihookingprotection.cpp
|
||||||
|
HEADERS += antihookingprotection.h
|
||||||
@@ -0,0 +1,161 @@
|
|||||||
|
#include "antihookingprotection.h"
|
||||||
|
|
||||||
|
#include <NktHookLib.h>
|
||||||
|
|
||||||
|
typedef HMODULE (WINAPI *LoadLibraryAFunc)(LPCSTR lpLibFileName);
|
||||||
|
typedef HMODULE (WINAPI *LoadLibraryWFunc)(LPCWSTR lpLibFileName);
|
||||||
|
typedef HMODULE (WINAPI *LoadLibraryExAFunc)(LPCSTR lpLibFileName, HANDLE hFile, DWORD dwFlags);
|
||||||
|
typedef HMODULE (WINAPI *LoadLibraryExWFunc)(LPCWSTR lpLibFileName, HANDLE hFile, DWORD dwFlags);
|
||||||
|
|
||||||
|
class AntiHookingProtection
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
static void enable()
|
||||||
|
{
|
||||||
|
#ifdef QT_DEBUG
|
||||||
|
s_HookManager.SetEnableDebugOutput(true);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
HINSTANCE kernel32Handle = NktHookLibHelpers::GetModuleBaseAddress(L"kernel32.dll");
|
||||||
|
SIZE_T hookId;
|
||||||
|
|
||||||
|
s_HookManager.Hook(&hookId, (LPVOID*)&s_RealLoadLibraryA,
|
||||||
|
NktHookLibHelpers::GetProcedureAddress(kernel32Handle, "LoadLibraryA"),
|
||||||
|
(LPVOID)AntiHookingProtection::LoadLibraryAHook);
|
||||||
|
s_HookManager.Hook(&hookId, (LPVOID*)&s_RealLoadLibraryW,
|
||||||
|
NktHookLibHelpers::GetProcedureAddress(kernel32Handle, "LoadLibraryW"),
|
||||||
|
(LPVOID)AntiHookingProtection::LoadLibraryWHook);
|
||||||
|
s_HookManager.Hook(&hookId, (LPVOID*)&s_RealLoadLibraryExA,
|
||||||
|
NktHookLibHelpers::GetProcedureAddress(kernel32Handle, "LoadLibraryExA"),
|
||||||
|
(LPVOID)AntiHookingProtection::LoadLibraryExAHook);
|
||||||
|
s_HookManager.Hook(&hookId, (LPVOID*)&s_RealLoadLibraryExW,
|
||||||
|
NktHookLibHelpers::GetProcedureAddress(kernel32Handle, "LoadLibraryExW"),
|
||||||
|
(LPVOID)AntiHookingProtection::LoadLibraryExWHook);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
static bool isImageBlacklistedW(LPCWSTR lpLibFileName)
|
||||||
|
{
|
||||||
|
LPCWSTR dllName;
|
||||||
|
|
||||||
|
// If the library has a path prefixed, remove it
|
||||||
|
dllName = wcsrchr(lpLibFileName, '\\');
|
||||||
|
if (!dllName) {
|
||||||
|
// No prefix, so use the full name
|
||||||
|
dllName = lpLibFileName;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// Advance past the backslash
|
||||||
|
dllName++;
|
||||||
|
}
|
||||||
|
|
||||||
|
// FIXME: We don't currently handle LoadLibrary calls where the
|
||||||
|
// library name does not include a file extension and the loader
|
||||||
|
// automatically assumes .dll.
|
||||||
|
|
||||||
|
for (int i = 0; i < ARRAYSIZE(k_BlacklistedDlls); i++) {
|
||||||
|
if (_wcsicmp(dllName, k_BlacklistedDlls[i]) == 0) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool isImageBlacklistedA(LPCSTR lpLibFileName)
|
||||||
|
{
|
||||||
|
int uniChars = MultiByteToWideChar(CP_THREAD_ACP, 0, lpLibFileName, -1, nullptr, 0);
|
||||||
|
if (uniChars > 0) {
|
||||||
|
PWCHAR wideBuffer = new WCHAR[uniChars];
|
||||||
|
uniChars = MultiByteToWideChar(CP_THREAD_ACP, 0,
|
||||||
|
lpLibFileName, -1,
|
||||||
|
wideBuffer, uniChars * sizeof(WCHAR));
|
||||||
|
if (uniChars > 0) {
|
||||||
|
bool ret = isImageBlacklistedW(wideBuffer);
|
||||||
|
delete[] wideBuffer;
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
delete[] wideBuffer;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Error path
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
static HMODULE LoadLibraryAHook(LPCSTR lpLibFileName)
|
||||||
|
{
|
||||||
|
if (lpLibFileName && isImageBlacklistedA(lpLibFileName)) {
|
||||||
|
SetLastError(ERROR_ACCESS_DISABLED_BY_POLICY);
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
return s_RealLoadLibraryA(lpLibFileName);
|
||||||
|
}
|
||||||
|
|
||||||
|
static HMODULE LoadLibraryWHook(LPCWSTR lpLibFileName)
|
||||||
|
{
|
||||||
|
if (lpLibFileName && isImageBlacklistedW(lpLibFileName)) {
|
||||||
|
SetLastError(ERROR_ACCESS_DISABLED_BY_POLICY);
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
return s_RealLoadLibraryW(lpLibFileName);
|
||||||
|
}
|
||||||
|
|
||||||
|
static HMODULE LoadLibraryExAHook(LPCSTR lpLibFileName, HANDLE hFile, DWORD dwFlags)
|
||||||
|
{
|
||||||
|
if (lpLibFileName && isImageBlacklistedA(lpLibFileName)) {
|
||||||
|
SetLastError(ERROR_ACCESS_DISABLED_BY_POLICY);
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
return s_RealLoadLibraryExA(lpLibFileName, hFile, dwFlags);
|
||||||
|
}
|
||||||
|
|
||||||
|
static HMODULE LoadLibraryExWHook(LPCWSTR lpLibFileName, HANDLE hFile, DWORD dwFlags)
|
||||||
|
{
|
||||||
|
if (lpLibFileName && isImageBlacklistedW(lpLibFileName)) {
|
||||||
|
SetLastError(ERROR_ACCESS_DISABLED_BY_POLICY);
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
return s_RealLoadLibraryExW(lpLibFileName, hFile, dwFlags);
|
||||||
|
}
|
||||||
|
|
||||||
|
static CNktHookLib s_HookManager;
|
||||||
|
static LoadLibraryAFunc s_RealLoadLibraryA;
|
||||||
|
static LoadLibraryWFunc s_RealLoadLibraryW;
|
||||||
|
static LoadLibraryExAFunc s_RealLoadLibraryExA;
|
||||||
|
static LoadLibraryExWFunc s_RealLoadLibraryExW;
|
||||||
|
|
||||||
|
static constexpr LPCWSTR k_BlacklistedDlls[] = {
|
||||||
|
// This DLL shipped with ASUS Sonic Radar 3 improperly handles
|
||||||
|
// D3D9 exclusive fullscreen in a way that causes CreateDeviceEx()
|
||||||
|
// to deadlock. https://github.com/moonlight-stream/moonlight-qt/issues/102
|
||||||
|
L"NahimicOSD.dll"
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
CNktHookLib AntiHookingProtection::s_HookManager;
|
||||||
|
LoadLibraryAFunc AntiHookingProtection::s_RealLoadLibraryA;
|
||||||
|
LoadLibraryWFunc AntiHookingProtection::s_RealLoadLibraryW;
|
||||||
|
LoadLibraryExAFunc AntiHookingProtection::s_RealLoadLibraryExA;
|
||||||
|
LoadLibraryExWFunc AntiHookingProtection::s_RealLoadLibraryExW;
|
||||||
|
|
||||||
|
AH_EXPORT void AntiHookingDummyImport() {}
|
||||||
|
|
||||||
|
extern "C"
|
||||||
|
BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID)
|
||||||
|
{
|
||||||
|
switch (fdwReason)
|
||||||
|
{
|
||||||
|
case DLL_PROCESS_ATTACH:
|
||||||
|
AntiHookingProtection::enable();
|
||||||
|
DisableThreadLibraryCalls(hinstDLL);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
};
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#ifdef ANTIHOOKING_LIBRARY
|
||||||
|
#define AH_EXPORT extern "C" __declspec(dllexport)
|
||||||
|
#else
|
||||||
|
#define AH_EXPORT extern "C" __declspec(dllimport)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
AH_EXPORT void AntiHookingDummyImport();
|
||||||
|
|
||||||
+2
-2
@@ -23,9 +23,9 @@
|
|||||||
<key>NSSupportsAutomaticGraphicsSwitching</key>
|
<key>NSSupportsAutomaticGraphicsSwitching</key>
|
||||||
<true/>
|
<true/>
|
||||||
<key>CFBundleVersion</key>
|
<key>CFBundleVersion</key>
|
||||||
<string>0.6.0</string>
|
<string>0.6.1</string>
|
||||||
<key>CFBundleShortVersionString</key>
|
<key>CFBundleShortVersionString</key>
|
||||||
<string>0.6.0</string>
|
<string>0.6.1</string>
|
||||||
<key>CFBundleDisplayName</key>
|
<key>CFBundleDisplayName</key>
|
||||||
<string>Moonlight</string>
|
<string>Moonlight</string>
|
||||||
</dict>
|
</dict>
|
||||||
|
|||||||
+15
-2
@@ -258,6 +258,19 @@ else:unix: LIBS += -L$$OUT_PWD/../soundio/ -lsoundio
|
|||||||
INCLUDEPATH += $$PWD/../soundio/libsoundio
|
INCLUDEPATH += $$PWD/../soundio/libsoundio
|
||||||
DEPENDPATH += $$PWD/../soundio/libsoundio
|
DEPENDPATH += $$PWD/../soundio/libsoundio
|
||||||
|
|
||||||
|
win32:CONFIG(release, debug|release): LIBS += -L$$OUT_PWD/../h264bitstream/release/ -lh264bitstream
|
||||||
|
else:win32:CONFIG(debug, debug|release): LIBS += -L$$OUT_PWD/../h264bitstream/debug/ -lh264bitstream
|
||||||
|
else:unix: LIBS += -L$$OUT_PWD/../h264bitstream/ -lh264bitstream
|
||||||
|
|
||||||
|
INCLUDEPATH += $$PWD/../h264bitstream/h264bitstream
|
||||||
|
DEPENDPATH += $$PWD/../h264bitstream/h264bitstream
|
||||||
|
|
||||||
|
win32:CONFIG(release, debug|release): LIBS += -L$$OUT_PWD/../AntiHooking/release/ -lAntiHooking
|
||||||
|
else:win32:CONFIG(debug, debug|release): LIBS += -L$$OUT_PWD/../AntiHooking/debug/ -lAntiHooking
|
||||||
|
|
||||||
|
INCLUDEPATH += $$PWD/../AntiHooking
|
||||||
|
DEPENDPATH += $$PWD/../AntiHooking
|
||||||
|
|
||||||
unix:!macx: {
|
unix:!macx: {
|
||||||
isEmpty(PREFIX) {
|
isEmpty(PREFIX) {
|
||||||
PREFIX = /usr/local
|
PREFIX = /usr/local
|
||||||
@@ -302,5 +315,5 @@ macx {
|
|||||||
QMAKE_BUNDLE_DATA += APP_BUNDLE_RESOURCES
|
QMAKE_BUNDLE_DATA += APP_BUNDLE_RESOURCES
|
||||||
}
|
}
|
||||||
|
|
||||||
VERSION = 0.6.0
|
VERSION = 0.6.1
|
||||||
DEFINES += VERSION_STR=\\\"0.6.0\\\"
|
DEFINES += VERSION_STR=\\\"0.6.1\\\"
|
||||||
|
|||||||
@@ -33,6 +33,21 @@
|
|||||||
</screenshots>
|
</screenshots>
|
||||||
|
|
||||||
<releases>
|
<releases>
|
||||||
|
<release version="0.6.1" date="2018-10-14">
|
||||||
|
<description>
|
||||||
|
<p>New features:</p>
|
||||||
|
<ul>
|
||||||
|
<li>Added support for quitting Moonlight via gamepad</li>
|
||||||
|
<li>Added tooltips for games with very long names</li>
|
||||||
|
</ul>
|
||||||
|
<p>Bugfixes:</p>
|
||||||
|
<ul>
|
||||||
|
<li>Added a workaround for a memory leak in the VAAPI driver for AMD GPUs</li>
|
||||||
|
<li>Fixed combo boxes on the settings page being too small for certain DPI scaling</li>
|
||||||
|
<li>Reduced power usage when Moonlight is idling in the background for a while</li>
|
||||||
|
</ul>
|
||||||
|
</description>
|
||||||
|
</release>
|
||||||
<release version="0.6.0" date="2018-10-06">
|
<release version="0.6.0" date="2018-10-06">
|
||||||
<description>
|
<description>
|
||||||
<p>New features:</p>
|
<p>New features:</p>
|
||||||
|
|||||||
@@ -100,6 +100,12 @@ GridView {
|
|||||||
horizontalAlignment: Text.AlignHCenter
|
horizontalAlignment: Text.AlignHCenter
|
||||||
wrapMode: Text.Wrap
|
wrapMode: Text.Wrap
|
||||||
elide: Text.ElideRight
|
elide: Text.ElideRight
|
||||||
|
|
||||||
|
// Display a tooltip with the full name if it's truncated
|
||||||
|
ToolTip.text: model.name
|
||||||
|
ToolTip.delay: 1000
|
||||||
|
ToolTip.timeout: 5000
|
||||||
|
ToolTip.visible: (parent.hovered || parent.highlighted) && truncated
|
||||||
}
|
}
|
||||||
|
|
||||||
function launchOrResumeSelectedApp()
|
function launchOrResumeSelectedApp()
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import QtQuick 2.11
|
import QtQuick 2.9
|
||||||
import QtQuick.Controls 2.2
|
import QtQuick.Controls 2.2
|
||||||
|
|
||||||
// https://stackoverflow.com/questions/45029968/how-do-i-set-the-combobox-width-to-fit-the-largest-item
|
// https://stackoverflow.com/questions/45029968/how-do-i-set-the-combobox-width-to-fit-the-largest-item
|
||||||
@@ -9,17 +9,17 @@ ComboBox {
|
|||||||
|
|
||||||
TextMetrics {
|
TextMetrics {
|
||||||
id: popupMetrics
|
id: popupMetrics
|
||||||
font: popup.font
|
|
||||||
}
|
}
|
||||||
|
|
||||||
TextMetrics {
|
TextMetrics {
|
||||||
id: textMetrics
|
id: textMetrics
|
||||||
font: parent.font
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// We call this every time the options change (and init)
|
// We call this every time the options change (and init)
|
||||||
// so we can adjust the combo box width here too
|
// so we can adjust the combo box width here too
|
||||||
onActivated: {
|
onActivated: {
|
||||||
|
textMetrics.font = font
|
||||||
|
popupMetrics.font = popup.font
|
||||||
textWidth = 0
|
textWidth = 0
|
||||||
for (var i = 0; i < count; i++){
|
for (var i = 0; i < count; i++){
|
||||||
textMetrics.text = textAt(i)
|
textMetrics.text = textAt(i)
|
||||||
|
|||||||
+49
-14
@@ -48,12 +48,18 @@ ApplicationWindow {
|
|||||||
if (depth > 1) {
|
if (depth > 1) {
|
||||||
stackView.pop()
|
stackView.pop()
|
||||||
}
|
}
|
||||||
|
else {
|
||||||
|
quitConfirmationDialog.open()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Keys.onBackPressed: {
|
Keys.onBackPressed: {
|
||||||
if (depth > 1) {
|
if (depth > 1) {
|
||||||
stackView.pop()
|
stackView.pop()
|
||||||
}
|
}
|
||||||
|
else {
|
||||||
|
quitConfirmationDialog.open()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Keys.onMenuPressed: {
|
Keys.onMenuPressed: {
|
||||||
@@ -68,21 +74,36 @@ ApplicationWindow {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
onVisibilityChanged: {
|
// This timer keeps us polling for 5 minutes of inactivity
|
||||||
// We don't want to just use 'active' here because that will stop polling if
|
// to allow the user to work with Moonlight on a second display
|
||||||
// we lose focus, which might be overzealous for users with multiple screens
|
// while dealing with configuration issues. This will ensure
|
||||||
// where we may be clearly visible on the other display. Ideally we'll poll
|
// machines come online even if the input focus isn't on Moonlight.
|
||||||
// only if the window is visible to the user (not if obscured by other windows),
|
Timer {
|
||||||
// but it seems difficult to do this portably.
|
id: inactivityTimer
|
||||||
var shouldPoll = visibility !== Window.Minimized && visibility !== Window.Hidden
|
interval: 5 * 60000
|
||||||
|
onTriggered: {
|
||||||
if (shouldPoll && !pollingActive) {
|
if (!active && pollingActive) {
|
||||||
ComputerManager.startPolling()
|
ComputerManager.stopPollingAsync()
|
||||||
pollingActive = true
|
pollingActive = false
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else if (!shouldPoll && pollingActive) {
|
}
|
||||||
ComputerManager.stopPollingAsync()
|
|
||||||
pollingActive = false
|
onActiveChanged: {
|
||||||
|
if (active) {
|
||||||
|
// Stop the inactivity timer
|
||||||
|
inactivityTimer.stop()
|
||||||
|
|
||||||
|
// Restart polling if it was stopped
|
||||||
|
if (!pollingActive) {
|
||||||
|
ComputerManager.startPolling()
|
||||||
|
pollingActive = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// Start the inactivity timer to stop polling
|
||||||
|
// if focus does not return within a few minutes.
|
||||||
|
inactivityTimer.restart()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -353,4 +374,18 @@ ApplicationWindow {
|
|||||||
Qt.openUrlExternally("https://github.com/moonlight-stream/moonlight-docs/wiki/Gamepad-Mapping");
|
Qt.openUrlExternally("https://github.com/moonlight-stream/moonlight-docs/wiki/Gamepad-Mapping");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// This dialog appears when quitting via keyboard or gamepad button
|
||||||
|
MessageDialog {
|
||||||
|
id: quitConfirmationDialog
|
||||||
|
modality:Qt.WindowModal
|
||||||
|
icon: StandardIcon.Warning
|
||||||
|
standardButtons: StandardButton.Yes | StandardButton.No
|
||||||
|
text: "Are you sure you want to quit?"
|
||||||
|
|
||||||
|
onYes: Qt.quit()
|
||||||
|
|
||||||
|
// For keyboard/gamepad navigation
|
||||||
|
onAccepted: Qt.quit()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,6 +16,10 @@
|
|||||||
#include "streaming/video/ffmpeg.h"
|
#include "streaming/video/ffmpeg.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef Q_OS_WIN32
|
||||||
|
#include "antihookingprotection.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
#include "cli/startstream.h"
|
#include "cli/startstream.h"
|
||||||
#include "cli/commandlineparser.h"
|
#include "cli/commandlineparser.h"
|
||||||
#include "path.h"
|
#include "path.h"
|
||||||
@@ -263,6 +267,12 @@ int main(int argc, char *argv[])
|
|||||||
SetUnhandledExceptionFilter(UnhandledExceptionHandler);
|
SetUnhandledExceptionFilter(UnhandledExceptionHandler);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef Q_OS_WIN32
|
||||||
|
// Force AntiHooking.dll to be statically imported and loaded
|
||||||
|
// by ntdll by calling a dummy function.
|
||||||
|
AntiHookingDummyImport();
|
||||||
|
#endif
|
||||||
|
|
||||||
QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
|
QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
|
||||||
|
|
||||||
// This avoids using the default keychain for SSL, which may cause
|
// This avoids using the default keychain for SSL, which may cause
|
||||||
|
|||||||
+44
-22
@@ -350,6 +350,22 @@ void Session::initialize()
|
|||||||
m_StreamConfig.width,
|
m_StreamConfig.width,
|
||||||
m_StreamConfig.height,
|
m_StreamConfig.height,
|
||||||
m_StreamConfig.fps);
|
m_StreamConfig.fps);
|
||||||
|
#ifdef Q_OS_DARWIN
|
||||||
|
{
|
||||||
|
// Prior to GFE 3.11, GFE did not allow us to constrain
|
||||||
|
// the number of reference frames, so we have to fixup the SPS
|
||||||
|
// to allow decoding via VideoToolbox on macOS. Since we don't
|
||||||
|
// have fixup code for HEVC, just avoid it if GFE is too old.
|
||||||
|
QVector<int> gfeVersion = NvHTTP::parseQuad(m_Computer->gfeVersion);
|
||||||
|
if (gfeVersion.isEmpty() || // Very old versions don't have GfeVersion at all
|
||||||
|
gfeVersion[0] < 3 ||
|
||||||
|
(gfeVersion[0] == 3 && gfeVersion[1] < 11)) {
|
||||||
|
SDL_LogWarn(SDL_LOG_CATEGORY_APPLICATION,
|
||||||
|
"Disabling HEVC on macOS due to old GFE version");
|
||||||
|
m_StreamConfig.supportsHevc = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
m_StreamConfig.enableHdr = false;
|
m_StreamConfig.enableHdr = false;
|
||||||
break;
|
break;
|
||||||
case StreamingPreferences::VCC_FORCE_H264:
|
case StreamingPreferences::VCC_FORCE_H264:
|
||||||
@@ -689,9 +705,13 @@ void Session::updateOptimalWindowDisplayMode()
|
|||||||
bestMode = desktopMode;
|
bestMode = desktopMode;
|
||||||
}
|
}
|
||||||
|
|
||||||
SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION,
|
if ((SDL_GetWindowFlags(m_Window) & SDL_WINDOW_FULLSCREEN_DESKTOP) == SDL_WINDOW_FULLSCREEN) {
|
||||||
"Chosen best display mode: %dx%dx%d",
|
// Only print when the window is actually in full-screen exclusive mode,
|
||||||
bestMode.w, bestMode.h, bestMode.refresh_rate);
|
// otherwise we're not actually using the mode we've set here
|
||||||
|
SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION,
|
||||||
|
"Chosen best display mode: %dx%dx%d",
|
||||||
|
bestMode.w, bestMode.h, bestMode.refresh_rate);
|
||||||
|
}
|
||||||
|
|
||||||
SDL_SetWindowDisplayMode(m_Window, &bestMode);
|
SDL_SetWindowDisplayMode(m_Window, &bestMode);
|
||||||
}
|
}
|
||||||
@@ -848,6 +868,27 @@ void Session::exec(int displayOriginX, int displayOriginY)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QSvgRenderer svgIconRenderer(QString(":/res/moonlight.svg"));
|
||||||
|
QImage svgImage(ICON_SIZE, ICON_SIZE, QImage::Format_RGBA8888);
|
||||||
|
svgImage.fill(0);
|
||||||
|
|
||||||
|
QPainter svgPainter(&svgImage);
|
||||||
|
svgIconRenderer.render(&svgPainter);
|
||||||
|
SDL_Surface* iconSurface = SDL_CreateRGBSurfaceWithFormatFrom((void*)svgImage.constBits(),
|
||||||
|
svgImage.width(),
|
||||||
|
svgImage.height(),
|
||||||
|
32,
|
||||||
|
4 * svgImage.width(),
|
||||||
|
SDL_PIXELFORMAT_RGBA32);
|
||||||
|
#ifndef Q_OS_DARWIN
|
||||||
|
// Other platforms seem to preserve our Qt icon when creating a new window.
|
||||||
|
if (iconSurface != nullptr) {
|
||||||
|
// This must be called before entering full-screen mode on Windows
|
||||||
|
// or our icon will not persist when toggling to windowed mode
|
||||||
|
SDL_SetWindowIcon(m_Window, iconSurface);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
// For non-full screen windows, call getWindowDimensions()
|
// For non-full screen windows, call getWindowDimensions()
|
||||||
// again after creating a window to allow it to account
|
// again after creating a window to allow it to account
|
||||||
// for window chrome size.
|
// for window chrome size.
|
||||||
@@ -871,25 +912,6 @@ void Session::exec(int displayOriginX, int displayOriginY)
|
|||||||
SDL_SetWindowFullscreen(m_Window, m_FullScreenFlag);
|
SDL_SetWindowFullscreen(m_Window, m_FullScreenFlag);
|
||||||
}
|
}
|
||||||
|
|
||||||
QSvgRenderer svgIconRenderer(QString(":/res/moonlight.svg"));
|
|
||||||
QImage svgImage(ICON_SIZE, ICON_SIZE, QImage::Format_RGBA8888);
|
|
||||||
svgImage.fill(0);
|
|
||||||
|
|
||||||
QPainter svgPainter(&svgImage);
|
|
||||||
svgIconRenderer.render(&svgPainter);
|
|
||||||
SDL_Surface* iconSurface = SDL_CreateRGBSurfaceWithFormatFrom((void*)svgImage.constBits(),
|
|
||||||
svgImage.width(),
|
|
||||||
svgImage.height(),
|
|
||||||
32,
|
|
||||||
4 * svgImage.width(),
|
|
||||||
SDL_PIXELFORMAT_RGBA32);
|
|
||||||
#ifndef Q_OS_DARWIN
|
|
||||||
// Other platforms seem to preserve our Qt icon when creating a new window
|
|
||||||
if (iconSurface != nullptr) {
|
|
||||||
SDL_SetWindowIcon(m_Window, iconSurface);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef QT_DEBUG
|
#ifndef QT_DEBUG
|
||||||
// Capture the mouse by default on release builds only.
|
// Capture the mouse by default on release builds only.
|
||||||
// This prevents the mouse from becoming trapped inside
|
// This prevents the mouse from becoming trapped inside
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
#include <QString>
|
||||||
|
|
||||||
#include "vaapi.h"
|
#include "vaapi.h"
|
||||||
#include <streaming/streamutils.h>
|
#include <streaming/streamutils.h>
|
||||||
|
|
||||||
@@ -114,6 +116,21 @@ VAAPIRenderer::initialize(SDL_Window* window, int, int width, int height, int, b
|
|||||||
"Driver: %s",
|
"Driver: %s",
|
||||||
vendorString ? vendorString : "<unknown>");
|
vendorString ? vendorString : "<unknown>");
|
||||||
|
|
||||||
|
// AMD's Gallium VAAPI driver has a nasty memory leak
|
||||||
|
// that causes memory to be leaked for each submitted frame.
|
||||||
|
// The Flatpak runtime has a VDPAU driver in place that works
|
||||||
|
// well, so use that instead on AMD systems.
|
||||||
|
if (vendorString && qgetenv("FORCE_VAAPI") != "1") {
|
||||||
|
QString vendorStr(vendorString);
|
||||||
|
if (vendorStr.contains("AMD", Qt::CaseInsensitive) ||
|
||||||
|
vendorStr.contains("Radeon", Qt::CaseInsensitive)) {
|
||||||
|
// Fail and let VDPAU pick this up
|
||||||
|
SDL_LogWarn(SDL_LOG_CATEGORY_APPLICATION,
|
||||||
|
"Avoiding VAAPI on AMD driver");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// This will populate the driver_quirks
|
// This will populate the driver_quirks
|
||||||
err = av_hwdevice_ctx_init(m_HwContext);
|
err = av_hwdevice_ctx_init(m_HwContext);
|
||||||
if (err < 0) {
|
if (err < 0) {
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
#include <Limelight.h>
|
#include <Limelight.h>
|
||||||
#include "ffmpeg.h"
|
#include "ffmpeg.h"
|
||||||
#include "streaming/streamutils.h"
|
#include "streaming/streamutils.h"
|
||||||
|
#include <h264_stream.h>
|
||||||
|
|
||||||
#ifdef Q_OS_WIN32
|
#ifdef Q_OS_WIN32
|
||||||
#include "ffmpeg-renderers/dxva2.h"
|
#include "ffmpeg-renderers/dxva2.h"
|
||||||
@@ -21,6 +22,8 @@
|
|||||||
// This is gross but it allows us to use sizeof()
|
// This is gross but it allows us to use sizeof()
|
||||||
#include "ffmpeg_videosamples.cpp"
|
#include "ffmpeg_videosamples.cpp"
|
||||||
|
|
||||||
|
#define MAX_SPS_EXTRA_SIZE 16
|
||||||
|
|
||||||
#define FAILED_DECODES_RESET_THRESHOLD 20
|
#define FAILED_DECODES_RESET_THRESHOLD 20
|
||||||
|
|
||||||
bool FFmpegVideoDecoder::isHardwareAccelerated()
|
bool FFmpegVideoDecoder::isHardwareAccelerated()
|
||||||
@@ -62,7 +65,8 @@ FFmpegVideoDecoder::FFmpegVideoDecoder()
|
|||||||
m_ConsecutiveFailedDecodes(0),
|
m_ConsecutiveFailedDecodes(0),
|
||||||
m_Pacer(nullptr),
|
m_Pacer(nullptr),
|
||||||
m_LastFrameNumber(0),
|
m_LastFrameNumber(0),
|
||||||
m_StreamFps(0)
|
m_StreamFps(0),
|
||||||
|
m_NeedsSpsFixup(false)
|
||||||
{
|
{
|
||||||
av_init_packet(&m_Pkt);
|
av_init_packet(&m_Pkt);
|
||||||
SDL_AtomicSet(&m_QueuedFrames, 0);
|
SDL_AtomicSet(&m_QueuedFrames, 0);
|
||||||
@@ -225,6 +229,17 @@ bool FFmpegVideoDecoder::completeInitialization(AVCodec* decoder, SDL_Window* wi
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else {
|
||||||
|
if ((videoFormat & VIDEO_FORMAT_MASK_H264) &&
|
||||||
|
!(m_Renderer->getDecoderCapabilities() & CAPABILITY_REFERENCE_FRAME_INVALIDATION_AVC)) {
|
||||||
|
SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION,
|
||||||
|
"Using H.264 SPS fixup");
|
||||||
|
m_NeedsSpsFixup = true;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
m_NeedsSpsFixup = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef QT_DEBUG
|
#ifdef QT_DEBUG
|
||||||
// Restore default log level before streaming
|
// Restore default log level before streaming
|
||||||
@@ -424,6 +439,49 @@ bool FFmpegVideoDecoder::initialize(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void FFmpegVideoDecoder::writeBuffer(PLENTRY entry, int& offset)
|
||||||
|
{
|
||||||
|
if (m_NeedsSpsFixup && entry->bufferType == BUFFER_TYPE_SPS) {
|
||||||
|
const char naluHeader[] = {0x00, 0x00, 0x00, 0x01};
|
||||||
|
h264_stream_t* stream = h264_new();
|
||||||
|
int nalStart, nalEnd;
|
||||||
|
|
||||||
|
// Read the old NALU
|
||||||
|
find_nal_unit((uint8_t*)entry->data, entry->length, &nalStart, &nalEnd);
|
||||||
|
read_nal_unit(stream,
|
||||||
|
(unsigned char *)&entry->data[nalStart],
|
||||||
|
nalEnd - nalStart);
|
||||||
|
|
||||||
|
SDL_assert(nalStart == sizeof(naluHeader));
|
||||||
|
SDL_assert(nalEnd == entry->length);
|
||||||
|
|
||||||
|
// Fixup the SPS to what OS X needs to use hardware acceleration
|
||||||
|
stream->sps->num_ref_frames = 1;
|
||||||
|
stream->sps->vui.max_dec_frame_buffering = 1;
|
||||||
|
|
||||||
|
int initialOffset = offset;
|
||||||
|
|
||||||
|
// Copy the modified NALU data. This assumes a 3 byte prefix and
|
||||||
|
// begins writing from the 2nd byte, so we must write the data
|
||||||
|
// first, then go back and write the Annex B prefix.
|
||||||
|
offset += write_nal_unit(stream, (uint8_t*)&m_DecodeBuffer.data()[initialOffset + 3],
|
||||||
|
MAX_SPS_EXTRA_SIZE + entry->length - sizeof(naluHeader));
|
||||||
|
|
||||||
|
// Copy the NALU prefix over from the original SPS
|
||||||
|
memcpy(&m_DecodeBuffer.data()[initialOffset], naluHeader, sizeof(naluHeader));
|
||||||
|
offset += sizeof(naluHeader);
|
||||||
|
|
||||||
|
h264_free(stream);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// Write the buffer as-is
|
||||||
|
memcpy(&m_DecodeBuffer.data()[offset],
|
||||||
|
entry->data,
|
||||||
|
entry->length);
|
||||||
|
offset += entry->length;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
int FFmpegVideoDecoder::submitDecodeUnit(PDECODE_UNIT du)
|
int FFmpegVideoDecoder::submitDecodeUnit(PDECODE_UNIT du)
|
||||||
{
|
{
|
||||||
PLENTRY entry = du->bufferList;
|
PLENTRY entry = du->bufferList;
|
||||||
@@ -461,23 +519,23 @@ int FFmpegVideoDecoder::submitDecodeUnit(PDECODE_UNIT du)
|
|||||||
m_LastFrameNumber = du->frameNumber;
|
m_LastFrameNumber = du->frameNumber;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (du->fullLength + AV_INPUT_BUFFER_PADDING_SIZE > m_DecodeBuffer.length()) {
|
int requiredBufferSize = du->fullLength;
|
||||||
m_DecodeBuffer = QByteArray(du->fullLength + AV_INPUT_BUFFER_PADDING_SIZE, 0);
|
if (du->frameType == FRAME_TYPE_IDR) {
|
||||||
|
// Add some extra space in case we need to do an SPS fixup
|
||||||
|
requiredBufferSize += MAX_SPS_EXTRA_SIZE;
|
||||||
|
}
|
||||||
|
if (requiredBufferSize + AV_INPUT_BUFFER_PADDING_SIZE > m_DecodeBuffer.length()) {
|
||||||
|
m_DecodeBuffer = QByteArray(requiredBufferSize + AV_INPUT_BUFFER_PADDING_SIZE, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
int offset = 0;
|
int offset = 0;
|
||||||
while (entry != nullptr) {
|
while (entry != nullptr) {
|
||||||
memcpy(&m_DecodeBuffer.data()[offset],
|
writeBuffer(entry, offset);
|
||||||
entry->data,
|
|
||||||
entry->length);
|
|
||||||
offset += entry->length;
|
|
||||||
entry = entry->next;
|
entry = entry->next;
|
||||||
}
|
}
|
||||||
|
|
||||||
SDL_assert(offset == du->fullLength);
|
|
||||||
|
|
||||||
m_Pkt.data = reinterpret_cast<uint8_t*>(m_DecodeBuffer.data());
|
m_Pkt.data = reinterpret_cast<uint8_t*>(m_DecodeBuffer.data());
|
||||||
m_Pkt.size = du->fullLength;
|
m_Pkt.size = offset;
|
||||||
|
|
||||||
m_ActiveWndVideoStats.totalReassemblyTime += LiGetMillis() - du->receiveTimeMs;
|
m_ActiveWndVideoStats.totalReassemblyTime += LiGetMillis() - du->receiveTimeMs;
|
||||||
|
|
||||||
|
|||||||
@@ -40,6 +40,8 @@ private:
|
|||||||
|
|
||||||
void reset();
|
void reset();
|
||||||
|
|
||||||
|
void writeBuffer(PLENTRY entry, int& offset);
|
||||||
|
|
||||||
static
|
static
|
||||||
enum AVPixelFormat ffGetFormat(AVCodecContext* context,
|
enum AVPixelFormat ffGetFormat(AVCodecContext* context,
|
||||||
const enum AVPixelFormat* pixFmts);
|
const enum AVPixelFormat* pixFmts);
|
||||||
@@ -57,6 +59,7 @@ private:
|
|||||||
VIDEO_STATS m_GlobalVideoStats;
|
VIDEO_STATS m_GlobalVideoStats;
|
||||||
int m_LastFrameNumber;
|
int m_LastFrameNumber;
|
||||||
int m_StreamFps;
|
int m_StreamFps;
|
||||||
|
bool m_NeedsSpsFixup;
|
||||||
|
|
||||||
static const uint8_t k_H264TestFrame[];
|
static const uint8_t k_H264TestFrame[];
|
||||||
static const uint8_t k_HEVCTestFrame[];
|
static const uint8_t k_HEVCTestFrame[];
|
||||||
|
|||||||
Submodule
+1
Submodule h264bitstream/h264bitstream added at 34f3c58afa
@@ -0,0 +1,46 @@
|
|||||||
|
#-------------------------------------------------
|
||||||
|
#
|
||||||
|
# Project created by QtCreator 2018-10-12T15:50:59
|
||||||
|
#
|
||||||
|
#-------------------------------------------------
|
||||||
|
|
||||||
|
|
||||||
|
QT -= core gui
|
||||||
|
|
||||||
|
TARGET = h264bitstream
|
||||||
|
TEMPLATE = lib
|
||||||
|
|
||||||
|
# Support debug and release builds from command line for CI
|
||||||
|
CONFIG += debug_and_release
|
||||||
|
|
||||||
|
# Ensure symbols are always generated
|
||||||
|
CONFIG += force_debug_info
|
||||||
|
|
||||||
|
# Build a static library
|
||||||
|
CONFIG += staticlib
|
||||||
|
|
||||||
|
# Disable warnings
|
||||||
|
CONFIG += warn_off
|
||||||
|
|
||||||
|
# Older GCC versions defaulted to GNU89
|
||||||
|
*-g++ {
|
||||||
|
QMAKE_CFLAGS += -std=gnu99
|
||||||
|
}
|
||||||
|
|
||||||
|
SRC_DIR = $$PWD/h264bitstream
|
||||||
|
|
||||||
|
SOURCES += \
|
||||||
|
$$SRC_DIR/h264_avcc.c \
|
||||||
|
$$SRC_DIR/h264_nal.c \
|
||||||
|
$$SRC_DIR/h264_sei.c \
|
||||||
|
$$SRC_DIR/h264_slice_data.c \
|
||||||
|
$$SRC_DIR/h264_stream.c
|
||||||
|
|
||||||
|
HEADERS += \
|
||||||
|
$$SRC_DIR/bs.h \
|
||||||
|
$$SRC_DIR/h264_avcc.h \
|
||||||
|
$$SRC_DIR/h264_sei.h \
|
||||||
|
$$SRC_DIR/h264_slice_data.h \
|
||||||
|
$$SRC_DIR/h264_stream.h
|
||||||
|
|
||||||
|
INCLUDEPATH += $$INC_DIR
|
||||||
@@ -0,0 +1,271 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2010-2013 Nektra S.A., Buenos Aires, Argentina.
|
||||||
|
* All rights reserved. Contact: http://www.nektra.com
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* This file is part of Deviare In-Proc
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* Commercial License Usage
|
||||||
|
* ------------------------
|
||||||
|
* Licensees holding valid commercial Deviare In-Proc licenses may use this
|
||||||
|
* file in accordance with the commercial license agreement provided with the
|
||||||
|
* Software or, alternatively, in accordance with the terms contained in
|
||||||
|
* a written agreement between you and Nektra. For licensing terms and
|
||||||
|
* conditions see http://www.nektra.com/licensing/. For further information
|
||||||
|
* use the contact form at http://www.nektra.com/contact/.
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* GNU General Public License Usage
|
||||||
|
* --------------------------------
|
||||||
|
* Alternatively, this file may be used under the terms of the GNU
|
||||||
|
* General Public License version 3.0 as published by the Free Software
|
||||||
|
* Foundation and appearing in the file LICENSE.GPL included in the
|
||||||
|
* packaging of this file. Please review the following information to
|
||||||
|
* ensure the GNU General Public License version 3.0 requirements will be
|
||||||
|
* met: http://www.gnu.org/copyleft/gpl.html.
|
||||||
|
*
|
||||||
|
**/
|
||||||
|
|
||||||
|
#ifndef _NKTHOOKLIB
|
||||||
|
#define _NKTHOOKLIB
|
||||||
|
|
||||||
|
#include <windows.h>
|
||||||
|
|
||||||
|
//-----------------------------------------------------------
|
||||||
|
|
||||||
|
#define NKTHOOKLIB_DontSkipInitialJumps 0x0001
|
||||||
|
#define NKTHOOKLIB_DontRemoveOnUnhook 0x0002
|
||||||
|
#define NKTHOOKLIB_DontSkipAnyJumps 0x0004
|
||||||
|
#define NKTHOOKLIB_SkipNullProcsToHook 0x0008
|
||||||
|
#define NKTHOOKLIB_UseAbsoluteIndirectJumps 0x0010
|
||||||
|
#define NKTHOOKLIB_DisallowReentrancy 0x0020
|
||||||
|
#define NKTHOOKLIB_DontEnableHooks 0x0040
|
||||||
|
|
||||||
|
#define NKTHOOKLIB_ProcessPlatformX86 1
|
||||||
|
#define NKTHOOKLIB_ProcessPlatformX64 2
|
||||||
|
|
||||||
|
#define NKTHOOKLIB_CurrentProcess ((HANDLE)(LONG_PTR)-1)
|
||||||
|
#define NKTHOOKLIB_CurrentThread ((HANDLE)(LONG_PTR)-2)
|
||||||
|
|
||||||
|
//-----------------------------------------------------------
|
||||||
|
|
||||||
|
class CNktHookLib
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
typedef struct tagHOOK_INFO {
|
||||||
|
SIZE_T nHookId;
|
||||||
|
LPVOID lpProcToHook;
|
||||||
|
LPVOID lpNewProcAddr;
|
||||||
|
//----
|
||||||
|
LPVOID lpCallOriginal;
|
||||||
|
} HOOK_INFO, *LPHOOK_INFO;
|
||||||
|
|
||||||
|
CNktHookLib();
|
||||||
|
~CNktHookLib();
|
||||||
|
|
||||||
|
DWORD Hook(__out SIZE_T *lpnHookId, __out LPVOID *lplpCallOriginal, __in LPVOID lpProcToHook,
|
||||||
|
__in LPVOID lpNewProcAddr, __in DWORD dwFlags=0);
|
||||||
|
DWORD Hook(__inout HOOK_INFO aHookInfo[], __in SIZE_T nCount, __in DWORD dwFlags=0);
|
||||||
|
DWORD Hook(__inout LPHOOK_INFO aHookInfo[], __in SIZE_T nCount, __in DWORD dwFlags = 0);
|
||||||
|
|
||||||
|
DWORD RemoteHook(__out SIZE_T *lpnHookId, __out LPVOID *lplpCallOriginal, __in DWORD dwPid,
|
||||||
|
__in LPVOID lpProcToHook, __in LPVOID lpNewProcAddr, __in DWORD dwFlags);
|
||||||
|
DWORD RemoteHook(__inout HOOK_INFO aHookInfo[], __in SIZE_T nCount, __in DWORD dwPid, __in DWORD dwFlags);
|
||||||
|
DWORD RemoteHook(__inout LPHOOK_INFO aHookInfo[], __in SIZE_T nCount, __in DWORD dwPid, __in DWORD dwFlags);
|
||||||
|
|
||||||
|
DWORD RemoteHook(__out SIZE_T *lpnHookId, __out LPVOID *lplpCallOriginal, __in HANDLE hProcess,
|
||||||
|
__in LPVOID lpProcToHook, __in LPVOID lpNewProcAddr, __in DWORD dwFlags);
|
||||||
|
DWORD RemoteHook(__inout HOOK_INFO aHookInfo[], __in SIZE_T nCount, __in HANDLE hProcess, __in DWORD dwFlags);
|
||||||
|
DWORD RemoteHook(__inout LPHOOK_INFO aHookInfo[], __in SIZE_T nCount, __in HANDLE hProcess, __in DWORD dwFlags);
|
||||||
|
|
||||||
|
DWORD Unhook(__in SIZE_T nHookId);
|
||||||
|
DWORD Unhook(__in HOOK_INFO aHookInfo[], __in SIZE_T nCount);
|
||||||
|
DWORD Unhook(__in LPHOOK_INFO aHookInfo[], __in SIZE_T nCount);
|
||||||
|
VOID UnhookProcess(__in DWORD dwPid);
|
||||||
|
VOID UnhookAll();
|
||||||
|
|
||||||
|
//NOTE: The following 2 (two) methods will remove the hooks from the internal list of hooks but the original
|
||||||
|
// hook(s) will remain active.
|
||||||
|
DWORD RemoveHook(__in SIZE_T nHookId, BOOL bDisable);
|
||||||
|
DWORD RemoveHook(__in HOOK_INFO aHookInfo[], __in SIZE_T nCount, __in BOOL bDisable);
|
||||||
|
DWORD RemoveHook(__in LPHOOK_INFO aHookInfo[], __in SIZE_T nCount, __in BOOL bDisable);
|
||||||
|
|
||||||
|
DWORD EnableHook(__in SIZE_T nHookId, __in BOOL bEnable);
|
||||||
|
DWORD EnableHook(__in HOOK_INFO aHookInfo[], __in SIZE_T nCount, __in BOOL bEnable);
|
||||||
|
DWORD EnableHook(__in LPHOOK_INFO aHookInfo[], __in SIZE_T nCount, __in BOOL bEnable);
|
||||||
|
|
||||||
|
DWORD SetSuspendThreadsWhileHooking(__in BOOL bEnable);
|
||||||
|
BOOL GetSuspendThreadsWhileHooking();
|
||||||
|
|
||||||
|
DWORD SetEnableDebugOutput(__in BOOL bEnable);
|
||||||
|
BOOL GetEnableDebugOutput();
|
||||||
|
|
||||||
|
void* __cdecl operator new(__in size_t nSize);
|
||||||
|
void* __cdecl operator new[](__in size_t nSize);
|
||||||
|
void* __cdecl operator new(__in size_t nSize, __inout void* lpInPlace);
|
||||||
|
void __cdecl operator delete(__inout void* p);
|
||||||
|
void __cdecl operator delete[](__inout void* p);
|
||||||
|
#if _MSC_VER >= 1200
|
||||||
|
void __cdecl operator delete(__inout void* p, __inout void* lpPlace);
|
||||||
|
#endif //_MSC_VER >= 1200
|
||||||
|
|
||||||
|
private:
|
||||||
|
DWORD HookCommon(__in LPVOID lpInfo, __in SIZE_T nCount, __in DWORD dwPid, __in DWORD dwFlags);
|
||||||
|
DWORD UnhookCommon(__in LPVOID lpInfo, __in SIZE_T nCount, __in DWORD dwFlags);
|
||||||
|
DWORD RemoveHookCommon(__in LPVOID lpInfo, __in SIZE_T nCount, __in BOOL bDisable, __in DWORD dwFlags);
|
||||||
|
DWORD EnableHookCommon(__in LPVOID lpInfo, __in SIZE_T nCount, __in BOOL bEnable, __in DWORD dwFlags);
|
||||||
|
|
||||||
|
private:
|
||||||
|
LPVOID lpInternals;
|
||||||
|
};
|
||||||
|
|
||||||
|
//-----------------------------------------------------------
|
||||||
|
|
||||||
|
namespace NktHookLibHelpers {
|
||||||
|
|
||||||
|
//NOTE: See "BuildNtSysCalls" below
|
||||||
|
typedef struct tagSYSCALLDEF {
|
||||||
|
LPSTR szNtApiNameA;
|
||||||
|
SIZE_T nOffset;
|
||||||
|
} SYSCALLDEF, *LPSYSCALLDEF;
|
||||||
|
|
||||||
|
//--------------------------------
|
||||||
|
|
||||||
|
//NOTE: See "SetApiResolverCallback" below
|
||||||
|
typedef LPVOID (__stdcall *lpfnInternalApiResolver)(__in_z LPCSTR szApiNameA, __in LPVOID lpUserParam);
|
||||||
|
|
||||||
|
//--------------------------------
|
||||||
|
|
||||||
|
HINSTANCE GetModuleBaseAddress(__in_z LPCWSTR szDllNameW);
|
||||||
|
LPVOID GetProcedureAddress(__in HINSTANCE hDll, __in LPCSTR szProcNameA);
|
||||||
|
|
||||||
|
HINSTANCE GetRemoteModuleBaseAddress(__in HANDLE hProcess, __in_z LPCWSTR szDllNameW, __in BOOL bScanMappedImages);
|
||||||
|
LPVOID GetRemoteProcedureAddress(__in HANDLE hProcess, __in HINSTANCE hDll, __in_z LPCSTR szProcNameA);
|
||||||
|
|
||||||
|
//--------------------------------
|
||||||
|
|
||||||
|
int sprintf_s(__out_z char *lpDest, __in size_t nMaxCount, __in_z const char *szFormatA, ...);
|
||||||
|
int vsnprintf(__out_z char *lpDest, __in size_t nMaxCount, __in_z const char *szFormatA, __in va_list lpArgList);
|
||||||
|
|
||||||
|
//only on XP or later
|
||||||
|
int swprintf_s(__out_z wchar_t *lpDest, __in size_t nMaxCount, __in_z const wchar_t *szFormatW, ...);
|
||||||
|
int vsnwprintf(__out_z wchar_t *lpDest, __in size_t nMaxCount, __in_z const wchar_t *szFormatW, __in va_list lpArgList);
|
||||||
|
|
||||||
|
//--------------------------------
|
||||||
|
|
||||||
|
//Returns a PROCESSOR_ARCHITECTURE_xxx value or -1 on error.
|
||||||
|
LONG GetProcessorArchitecture();
|
||||||
|
|
||||||
|
HANDLE OpenProcess(__in DWORD dwDesiredAccess, __in BOOL bInheritHandle, __in DWORD dwProcessId);
|
||||||
|
HANDLE OpenThread(__in DWORD dwDesiredAccess, __in BOOL bInheritHandle, __in DWORD dwThreadId);
|
||||||
|
|
||||||
|
LONG GetProcessPlatform(__in HANDLE hProcess);
|
||||||
|
|
||||||
|
SIZE_T ReadMem(__in HANDLE hProcess, __out LPVOID lpDest, __in LPVOID lpSrc, __in SIZE_T nBytesCount);
|
||||||
|
BOOL WriteMem(__in HANDLE hProcess, __out LPVOID lpDest, __in LPVOID lpSrc, __in SIZE_T nBytesCount);
|
||||||
|
|
||||||
|
LONG GetThreadPriority(__in HANDLE hThread, __out int *lpnPriority);
|
||||||
|
LONG SetThreadPriority(__in HANDLE hThread, __in int nPriority);
|
||||||
|
|
||||||
|
DWORD GetCurrentThreadId();
|
||||||
|
DWORD GetCurrentProcessId();
|
||||||
|
|
||||||
|
HANDLE GetProcessHeap();
|
||||||
|
LPVOID MemAlloc(__in SIZE_T nSize);
|
||||||
|
VOID MemFree(__in LPVOID lpPtr);
|
||||||
|
|
||||||
|
VOID MemSet(__out void *lpDest, __in int nVal, __in SIZE_T nCount);
|
||||||
|
VOID MemCopy(__out void *lpDest, __in const void *lpSrc, __in SIZE_T nCount);
|
||||||
|
SIZE_T TryMemCopy(__out void *lpDest, __in const void *lpSrc, __in SIZE_T nCount);
|
||||||
|
VOID MemMove(__out void *lpDest, __in const void *lpSrc, __in SIZE_T nCount);
|
||||||
|
int MemCompare(__in const void *lpBuf1, __in const void *lpBuf2, __in SIZE_T nCount);
|
||||||
|
|
||||||
|
//--------------------------------
|
||||||
|
|
||||||
|
VOID DebugPrint(__in LPCSTR szFormatA, ...);
|
||||||
|
VOID DebugVPrint(__in LPCSTR szFormatA, __in va_list argptr);
|
||||||
|
|
||||||
|
//--------------------------------
|
||||||
|
|
||||||
|
SIZE_T GetInstructionLength(__in LPVOID lpAddr, __in SIZE_T nSize, __in BYTE nPlatformBits,
|
||||||
|
__out_opt BOOL *lpbIsMemOp=NULL, __out_z_opt LPSTR szBufA=NULL, __in SIZE_T nBufLen=0);
|
||||||
|
|
||||||
|
//NOTE: When NktHookLib is initialized, it tries to locate needed ntdll's apis by scanning process' modules.
|
||||||
|
// If you want to override an api call, use this method to set the resolver address. LPVOID returned by
|
||||||
|
// the callback must have the same definition and calling convention than the one in ntdll. Return NULL
|
||||||
|
// if you want NktHookLib to use the real ntdll api.
|
||||||
|
VOID SetInternalApiResolverCallback(__in lpfnInternalApiResolver fnInternalApiResolver, __in LPVOID lpUserParam);
|
||||||
|
|
||||||
|
//This function generates a relocatable byte code with a copy of the original SysCall routine for each passes
|
||||||
|
//ntdll api. The code is created based on the original ntdll.dll image file on disk located on System32 or SysWow64,
|
||||||
|
//depending on the target platform.
|
||||||
|
//
|
||||||
|
//Useful for doing direct calls to low level apis bypassing third party hooks (like Chrome navigator does). Also, you
|
||||||
|
//can pass the generated code to another process. You can generate the code with this method, pass it to another
|
||||||
|
//process and then use SetApiResolverCallback above.
|
||||||
|
//
|
||||||
|
//NOTE: Not all NtXXX apis are SysCalls. Trying to generate code for a non-syscall api may generate an unexpected
|
||||||
|
// behavior.
|
||||||
|
// If 'lpCode' is NULL, the needed space is returned. Although syscalls uses less than 32 bytes, a maximum of 256
|
||||||
|
// bytes are supported for each requested api. You can safety allocate a block of 256*nDefsCount bytes to hold
|
||||||
|
// the generated code.
|
||||||
|
DWORD BuildNtSysCalls(__in LPSYSCALLDEF lpDefs, __in SIZE_T nDefsCount, __in SIZE_T nPlatform,
|
||||||
|
__out_opt LPVOID lpCode, __out SIZE_T *lpnCodeSize);
|
||||||
|
|
||||||
|
//--------------------------------
|
||||||
|
|
||||||
|
//NOTE: Return 0xFFFFFFFF if remote thread is not accessible
|
||||||
|
DWORD GetWin32LastError(__in_opt HANDLE hThread=NULL);
|
||||||
|
BOOL SetWin32LastError(__in DWORD dwErrorCode, __in_opt HANDLE hThread=NULL);
|
||||||
|
|
||||||
|
//--------------------------------
|
||||||
|
|
||||||
|
BOOL GetOsVersion(__out_opt LPDWORD lpdwVerMajor=NULL, __out_opt LPDWORD lpdwVerMinor=NULL,
|
||||||
|
__out_opt LPDWORD lpdwBuildNumber=NULL);
|
||||||
|
|
||||||
|
//--------------------------------
|
||||||
|
|
||||||
|
//NOTE: CreateProcessWithDllW and related functions returns the Win32 error code directly. NOERROR => Success.
|
||||||
|
//
|
||||||
|
// If "szDllNameW" string ends with 'x86.dll', 'x64.dll', '32.dll', '64.dll', the dll name will be adjusted
|
||||||
|
// in order to match the process platform. I.e.: "mydll_x86.dll" will become "mydll_x64.dll" on 64-bit processes.
|
||||||
|
DWORD CreateProcessWithDllW(__in_z_opt LPCWSTR lpApplicationName, __inout_z_opt LPWSTR lpCommandLine,
|
||||||
|
__in_opt LPSECURITY_ATTRIBUTES lpProcessAttributes,
|
||||||
|
__in_opt LPSECURITY_ATTRIBUTES lpThreadAttributes, __in BOOL bInheritHandles,
|
||||||
|
__in DWORD dwCreationFlags, __in_z_opt LPCWSTR lpEnvironment,
|
||||||
|
__in_z_opt LPCWSTR lpCurrentDirectory, __in LPSTARTUPINFOW lpStartupInfo,
|
||||||
|
__out LPPROCESS_INFORMATION lpProcessInformation, __in_z LPCWSTR szDllNameW,
|
||||||
|
__in_opt HANDLE hSignalCompleted=NULL, __in_z_opt LPCSTR szInitFunctionA=NULL,
|
||||||
|
__in_opt LPVOID lpInitFuncParams=NULL, __in_opt ULONG nInitFuncParamsSize=0);
|
||||||
|
|
||||||
|
DWORD CreateProcessWithLogonAndDllW(__in_z LPCWSTR lpUsername, __in_z_opt LPCWSTR lpDomain, __in_z LPCWSTR lpPassword,
|
||||||
|
__in DWORD dwLogonFlags, __in_opt LPCWSTR lpApplicationName,
|
||||||
|
__inout_opt LPWSTR lpCommandLine, __in DWORD dwCreationFlags,
|
||||||
|
__in_z_opt LPCWSTR lpEnvironment, __in_z_opt LPCWSTR lpCurrentDirectory,
|
||||||
|
__in LPSTARTUPINFOW lpStartupInfo, __out LPPROCESS_INFORMATION lpProcessInformation,
|
||||||
|
__in_z LPCWSTR szDllNameW, __in_opt HANDLE hSignalCompleted=NULL,
|
||||||
|
__in_z_opt LPCSTR szInitFunctionA=NULL, __in_opt LPVOID lpInitFuncParams=NULL,
|
||||||
|
__in_opt ULONG nInitFuncParamsSize=0);
|
||||||
|
|
||||||
|
DWORD CreateProcessWithTokenAndDllW(__in HANDLE hToken, __in DWORD dwLogonFlags, __in_z_opt LPCWSTR lpApplicationName,
|
||||||
|
__inout_opt LPWSTR lpCommandLine, __in DWORD dwCreationFlags,
|
||||||
|
__in_z_opt LPCWSTR lpEnvironment, __in_z_opt LPCWSTR lpCurrentDirectory,
|
||||||
|
__in LPSTARTUPINFOW lpStartupInfo, __out LPPROCESS_INFORMATION lpProcessInformation,
|
||||||
|
__in_z LPCWSTR szDllNameW, __in_opt HANDLE hSignalCompleted=NULL,
|
||||||
|
__in_z_opt LPCSTR szInitFunctionA=NULL, __in_opt LPVOID lpInitFuncParams=NULL,
|
||||||
|
__in_opt ULONG nInitFuncParamsSize=0);
|
||||||
|
|
||||||
|
DWORD InjectDllByPidW(__in DWORD dwPid, __in_z LPCWSTR szDllNameW, __in_z_opt LPCSTR szInitFunctionA=NULL,
|
||||||
|
__in_opt DWORD dwProcessInitWaitTimeoutMs=5000, __out_opt LPHANDLE lphInjectorThread=NULL,
|
||||||
|
__in_opt LPVOID lpInitFuncParams=NULL, __in_opt ULONG nInitFuncParamsSize=0);
|
||||||
|
|
||||||
|
DWORD InjectDllByHandleW(__in HANDLE hProcess, __in_z LPCWSTR szDllNameW, __in_z_opt LPCSTR szInitFunctionA=NULL,
|
||||||
|
__in_opt DWORD dwProcessInitWaitTimeoutMs=5000, __out_opt LPHANDLE lphInjectorThread=NULL,
|
||||||
|
__in_opt LPVOID lpInitFuncParams=NULL, __in_opt ULONG nInitFuncParamsSize=0);
|
||||||
|
|
||||||
|
} //NktHookLibHelpers
|
||||||
|
|
||||||
|
//-----------------------------------------------------------
|
||||||
|
|
||||||
|
#endif //_NKTHOOKLIB
|
||||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -67,7 +67,7 @@ INCLUDEPATH += \
|
|||||||
CONFIG += warn_off staticlib
|
CONFIG += warn_off staticlib
|
||||||
DEFINES += HAS_SOCKLEN_T
|
DEFINES += HAS_SOCKLEN_T
|
||||||
|
|
||||||
debug {
|
CONFIG(debug, debug|release) {
|
||||||
# Enable asserts on debug builds
|
# Enable asserts on debug builds
|
||||||
DEFINES += LC_DEBUG
|
DEFINES += LC_DEBUG
|
||||||
}
|
}
|
||||||
|
|||||||
+7
-2
@@ -3,10 +3,15 @@ SUBDIRS = \
|
|||||||
moonlight-common-c \
|
moonlight-common-c \
|
||||||
qmdnsengine \
|
qmdnsengine \
|
||||||
app \
|
app \
|
||||||
soundio
|
soundio \
|
||||||
|
h264bitstream
|
||||||
|
|
||||||
# Build the dependencies in parallel before the final app
|
# Build the dependencies in parallel before the final app
|
||||||
app.depends = qmdnsengine moonlight-common-c soundio
|
app.depends = qmdnsengine moonlight-common-c soundio h264bitstream
|
||||||
|
win32 {
|
||||||
|
SUBDIRS += AntiHooking
|
||||||
|
app.depends += AntiHooking
|
||||||
|
}
|
||||||
|
|
||||||
# Support debug and release builds from command line for CI
|
# Support debug and release builds from command line for CI
|
||||||
CONFIG += debug_and_release
|
CONFIG += debug_and_release
|
||||||
|
|||||||
@@ -92,6 +92,10 @@ echo Copying DLL dependencies
|
|||||||
copy %SOURCE_ROOT%\libs\windows\lib\%ARCH%\*.dll %DEPLOY_FOLDER%
|
copy %SOURCE_ROOT%\libs\windows\lib\%ARCH%\*.dll %DEPLOY_FOLDER%
|
||||||
if !ERRORLEVEL! NEQ 0 goto Error
|
if !ERRORLEVEL! NEQ 0 goto Error
|
||||||
|
|
||||||
|
echo Copying AntiHooking.dll
|
||||||
|
copy %BUILD_FOLDER%\AntiHooking\%BUILD_CONFIG%\AntiHooking.dll %DEPLOY_FOLDER%
|
||||||
|
if !ERRORLEVEL! NEQ 0 goto Error
|
||||||
|
|
||||||
echo Copying GC mapping list
|
echo Copying GC mapping list
|
||||||
copy %SOURCE_ROOT%\app\SDL_GameControllerDB\gamecontrollerdb.txt %DEPLOY_FOLDER%
|
copy %SOURCE_ROOT%\app\SDL_GameControllerDB\gamecontrollerdb.txt %DEPLOY_FOLDER%
|
||||||
if !ERRORLEVEL! NEQ 0 goto Error
|
if !ERRORLEVEL! NEQ 0 goto Error
|
||||||
@@ -110,10 +114,12 @@ if !ERRORLEVEL! NEQ 0 goto Error
|
|||||||
|
|
||||||
if "%SIGN%"=="1" (
|
if "%SIGN%"=="1" (
|
||||||
echo Signing deployed binaries
|
echo Signing deployed binaries
|
||||||
|
set FILES_TO_SIGN=
|
||||||
for /r "%DEPLOY_FOLDER%" %%f in (*.dll *.exe) do (
|
for /r "%DEPLOY_FOLDER%" %%f in (*.dll *.exe) do (
|
||||||
signtool %SIGNTOOL_PARAMS% %%f
|
set FILES_TO_SIGN=!FILES_TO_SIGN! %%f
|
||||||
if !ERRORLEVEL! NEQ 0 goto Error
|
|
||||||
)
|
)
|
||||||
|
signtool %SIGNTOOL_PARAMS% !FILES_TO_SIGN!
|
||||||
|
if !ERRORLEVEL! NEQ 0 goto Error
|
||||||
)
|
)
|
||||||
|
|
||||||
echo Building MSI
|
echo Building MSI
|
||||||
|
|||||||
+1
-1
Submodule soundio/libsoundio updated: 2bb21ad417...5d6a7210fa
@@ -23,6 +23,11 @@ CONFIG += staticlib
|
|||||||
QMAKE_CFLAGS += /TP
|
QMAKE_CFLAGS += /TP
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# Older GCC versions defaulted to GNU89
|
||||||
|
*-g++ {
|
||||||
|
QMAKE_CFLAGS += -std=gnu99
|
||||||
|
}
|
||||||
|
|
||||||
# Disable warnings
|
# Disable warnings
|
||||||
CONFIG += warn_off
|
CONFIG += warn_off
|
||||||
|
|
||||||
@@ -39,6 +44,11 @@ unix:!macx {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CONFIG(release, debug|release) {
|
||||||
|
# Disable asserts on release builds
|
||||||
|
DEFINES += NDEBUG
|
||||||
|
}
|
||||||
|
|
||||||
DEFINES += \
|
DEFINES += \
|
||||||
SOUNDIO_STATIC_LIBRARY \
|
SOUNDIO_STATIC_LIBRARY \
|
||||||
SOUNDIO_VERSION_MAJOR=1 \
|
SOUNDIO_VERSION_MAJOR=1 \
|
||||||
|
|||||||
Reference in New Issue
Block a user