9 Commits

Author SHA1 Message Date
neru d390304577 build: misc cmakelist fixes
Build / build (push) Failing after 4m55s
2026-06-20 07:03:01 -03:00
neru 037260acd5 style: run format 2026-06-20 06:59:39 -03:00
neru f30a76fe18 feat: add icon 2026-06-20 06:59:06 -03:00
neru 579e0d1352 feat: add mutex to prevent double runs 2026-06-20 06:53:20 -03:00
neru 26a4406c88 build: link libs for tray icon, change executable type 2026-06-20 06:53:15 -03:00
neru 385cfe147d feat: add tray icon 2026-06-20 06:53:02 -03:00
neru 98be88b346 fix: sort includes 2026-06-19 14:26:52 -03:00
neru bf83ae571d fix: undef error, include minwindef instead of windows 2026-06-19 14:26:34 -03:00
neru c1bc1023eb build: rollback cache version 2026-06-19 13:28:36 -03:00
11 changed files with 301 additions and 26 deletions
+1 -1
View File
@@ -56,7 +56,7 @@ jobs:
} >> $GITHUB_OUTPUT } >> $GITHUB_OUTPUT
- name: Cache FetchContent & ccache - name: Cache FetchContent & ccache
uses: actions/cache@v4 uses: actions/cache@v3
with: with:
path: | path: |
build/_deps build/_deps
+11 -12
View File
@@ -8,18 +8,18 @@ set(CMAKE_CXX_STANDARD 20)
add_compile_definitions(WIN32_LEAN_AND_MEAN NOMINMAX) add_compile_definitions(WIN32_LEAN_AND_MEAN NOMINMAX)
if(MSVC)
add_compile_options(/EHsc /utf-8 /Zc:char8_t)
if("${CMAKE_VS_PLATFORM_NAME}" STREQUAL "x64")
add_compile_definitions(_AMD64_)
endif()
else()
add_compile_options(-m64)
endif()
project(hex-unlocked LANGUAGES CXX) project(hex-unlocked LANGUAGES CXX)
set_property(GLOBAL PROPERTY USE_FOLDERS ON) set_property(GLOBAL PROPERTY USE_FOLDERS ON)
enable_language(RC)
if(CMAKE_GENERATOR MATCHES "Visual Studio")
add_compile_options(/EHsc /utf-8 /Zc:char8_t)
else()
add_compile_options(-m64)
add_link_options(-static -static-libgcc -static-libstdc++)
endif()
# ------------------------------ # ------------------------------
# options # options
# ------------------------------ # ------------------------------
@@ -37,7 +37,6 @@ endif()
# msvc stuff # msvc stuff
# ------------------------------ # ------------------------------
if(CMAKE_GENERATOR MATCHES "Visual Studio") if(CMAKE_GENERATOR MATCHES "Visual Studio")
string(APPEND CMAKE_CXX_FLAGS " /EHsc /DWIN32_LEAN_AND_MEAN /utf-8 /Zc:char8_t")
if("${CMAKE_VS_PLATFORM_NAME}" STREQUAL "x64") if("${CMAKE_VS_PLATFORM_NAME}" STREQUAL "x64")
string(APPEND CMAKE_CXX_FLAGS " /D_AMD64_") string(APPEND CMAKE_CXX_FLAGS " /D_AMD64_")
elseif(CMAKE_GENERATOR_PLATFORM STREQUAL "Win32") elseif(CMAKE_GENERATOR_PLATFORM STREQUAL "Win32")
@@ -138,8 +137,8 @@ endif()
# ------------------------------ # ------------------------------
file(GLOB_RECURSE UNLOCKER_SOURCES CONFIGURE_DEPENDS "src/unlocker/*.cpp" "src/unlocker/*.h") file(GLOB_RECURSE UNLOCKER_SOURCES CONFIGURE_DEPENDS "src/unlocker/*.cpp" "src/unlocker/*.h")
add_executable(hex-unlocked ${UNLOCKER_SOURCES}) add_executable(hex-unlocked WIN32 ${UNLOCKER_SOURCES} "res/resources.rc")
target_link_libraries(hex-unlocked PRIVATE hex-warned seallib glaze::glaze tinymitm wininet ixwebsocket crypt32) target_link_libraries(hex-unlocked PRIVATE hex-warned seallib glaze::glaze tinymitm wininet ixwebsocket crypt32 user32 shell32)
# rnd exe name # rnd exe name
string(RANDOM LENGTH 12 ALPHABET "abcdefghijklmnopqrstuvwxyz0123456789" RANDOM_EXE_NAME) string(RANDOM LENGTH 12 ALPHABET "abcdefghijklmnopqrstuvwxyz0123456789" RANDOM_EXE_NAME)
BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 156 KiB

+1
View File
@@ -0,0 +1 @@
IDI_ICON1 ICON DISCARDABLE "icon.ico"
+1
View File
@@ -1,4 +1,5 @@
#include "cache-cleaner.h" #include "cache-cleaner.h"
#include "win-platform.h" #include "win-platform.h"
#include <filesystem> #include <filesystem>
+73 -9
View File
@@ -1,15 +1,15 @@
#include <seallib/log.h> #include "win-platform.h"
#include <tinymitm/proxy.h> #include "tray-icon.h"
#include <memory>
#include "utils.h" #include "utils.h"
#include "spoofer.h" #include "spoofer.h"
#include "log-sink.h" #include "log-sink.h"
#include "proxy-configurator.h" #include "proxy-configurator.h"
#include "cache-cleaner.h" #include "cache-cleaner.h"
#include "win-platform.h" #include <seallib/log.h>
#include <tinymitm/proxy.h>
#include <memory>
#include <processenv.h> #include <processenv.h>
#include <cassert> #include <cassert>
@@ -71,6 +71,21 @@ void StartWatchdog()
bool run() bool run()
{ {
/*
mutex check before running
*/
HANDLE mtx = CreateMutexA(NULL, TRUE, "Global\\HexUnlocked");
if (mtx == NULL) return false;
if (GetLastError() == ERROR_ALREADY_EXISTS)
{
MessageBoxA(NULL, "Program is already running", "Hex: Unlocked", MB_OK | MB_ICONERROR | MB_ICONINFORMATION);
CloseHandle(mtx);
return false;
}
/*
init
*/
seallib::Logger mainLog("Main"); seallib::Logger mainLog("Main");
mainLog.addSink(std::make_shared<ConOutSink>()); mainLog.addSink(std::make_shared<ConOutSink>());
@@ -104,11 +119,36 @@ bool run()
return false; return false;
} }
mainLog.info("Proxy running, Ctrl+C to stop."); mainLog.info("Setting up system tray icon");
TrayIcon tray;
tray.setExitCallback([&]() {
running = false;
mainLog.info("Exit requested from system tray.");
});
if (!tray.init())
{
mainLog.error("Failed to initialize system tray icon.");
return false;
}
HWND consoleWnd = GetConsoleWindow();
if (consoleWnd)
{
HMENU menuHandle = GetSystemMenu(consoleWnd, FALSE);
if (menuHandle) RemoveMenu(menuHandle, SC_CLOSE, MF_BYCOMMAND);
}
mainLog.info("Proxy running, Ctrl+C to stop. Check system tray for options.");
while (running) while (running)
std::this_thread::sleep_for(std::chrono::milliseconds(100)); {
tray.processMessages();
std::this_thread::sleep_for(std::chrono::milliseconds(50));
}
mainLog.info("Shutting down..."); mainLog.info("Shutting down...");
tray.shutdown();
proxy->shutdown(); proxy->shutdown();
cleaner->shutdown(); cleaner->shutdown();
@@ -117,11 +157,35 @@ bool run()
delete conf; delete conf;
conf = nullptr; conf = nullptr;
ReleaseMutex(mtx);
CloseHandle(mtx);
return true; return true;
} }
int main() int WINAPI WinMain(HINSTANCE /*hInstance*/, HINSTANCE /*hPrevInstance*/, LPSTR /*lpCmdLine*/, int /*nShowCmd*/)
{ {
AllocConsole();
/*
ansi seequences
*/
HANDLE outHandle = GetStdHandle(STD_OUTPUT_HANDLE);
if (outHandle == INVALID_HANDLE_VALUE) return 1;
DWORD conMode = 0;
if (!GetConsoleMode(outHandle, &conMode)) return 1;
conMode |= ENABLE_VIRTUAL_TERMINAL_PROCESSING;
SetConsoleMode(outHandle, conMode);
/*
io
*/
FILE* dummy;
freopen_s(&dummy, "CONIN$", "r", stdin);
freopen_s(&dummy, "CONOUT$", "w", stdout);
freopen_s(&dummy, "CONOUT$", "w", stderr);
/* /*
handlers for cleaning proxy conf on exit / crash / taskkill / whatever handlers for cleaning proxy conf on exit / crash / taskkill / whatever
+3 -2
View File
@@ -1,13 +1,14 @@
#include "proxy-configurator.h" #include "proxy-configurator.h"
#include "log-sink.h"
#include "win-platform.h" #include "win-platform.h"
#include "log-sink.h"
#include <minwinbase.h> #include <minwinbase.h>
#include <wininet.h> #include <wininet.h>
#include <errhandlingapi.h> #include <errhandlingapi.h>
#include <seallib/log.h>
ProxyConfigurator::ProxyConfigurator() ProxyConfigurator::ProxyConfigurator()
{ {
_log = new seallib::Logger("ProxyConfigurator"); _log = new seallib::Logger("ProxyConfigurator");
+175
View File
@@ -0,0 +1,175 @@
#include "tray-icon.h"
#include "win-platform.h"
#include <shellapi.h>
#include <iostream>
#define WM_TRAYICON (WM_USER + 1)
#define ID_TRAY_APP_ICON 1001
#define ID_TRAY_EXIT 1002
#define ID_TRAY_CONTROL_PANEL 1003
TrayIcon* TrayIcon::instance = nullptr;
TrayIcon::TrayIcon() : _hwnd(nullptr), _isConsoleVisible(true)
{
instance = this;
}
TrayIcon::~TrayIcon()
{
shutdown();
instance = nullptr;
}
void* TrayIcon::windowProc(void* h, unsigned int msg, unsigned long long wParam, long long lParam)
{
HWND hwnd = reinterpret_cast<HWND>(h);
if (msg == WM_DESTROY)
{
PostQuitMessage(0);
return 0;
}
if (msg == WM_TRAYICON)
{
if (lParam == WM_LBUTTONUP && instance)
instance->onToggleConsole();
else if (lParam == WM_RBUTTONUP)
{
POINT curPoint;
GetCursorPos(&curPoint);
HMENU popupHandle = CreatePopupMenu();
InsertMenuA(popupHandle, 0, MF_BYPOSITION | MF_STRING, ID_TRAY_CONTROL_PANEL, "Open Control Panel");
InsertMenuA(popupHandle, 1, MF_BYPOSITION | MF_STRING, ID_TRAY_EXIT, "Exit");
SetForegroundWindow(hwnd);
UINT clicked =
TrackPopupMenu(popupHandle, TPM_RETURNCMD | TPM_NONOTIFY, curPoint.x, curPoint.y, 0, hwnd, NULL);
if (clicked == ID_TRAY_CONTROL_PANEL && instance)
instance->onOpenControlPanel();
else if (clicked == ID_TRAY_EXIT && instance)
instance->onExit();
DestroyMenu(popupHandle);
}
}
return reinterpret_cast<void*>(DefWindowProcA(hwnd, msg, wParam, lParam));
}
bool TrayIcon::init()
{
WNDCLASSEXA wc = {0};
wc.cbSize = sizeof(WNDCLASSEX);
wc.lpfnWndProc = (WNDPROC)windowProc;
wc.hInstance = GetModuleHandle(NULL);
wc.lpszClassName = "HexUnlockedTrayIconClass";
if (!RegisterClassExA(&wc)) return false;
HWND window = CreateWindowExA(0, "HexUnlockedTrayIconClass", "HexUnlocked", 0, 0, 0, 0, 0, HWND_MESSAGE, NULL,
wc.hInstance, NULL);
if (!window) return false;
this->_hwnd = window;
NOTIFYICONDATAA nid = {0};
nid.cbSize = sizeof(NOTIFYICONDATA);
nid.hWnd = window;
nid.uID = ID_TRAY_APP_ICON;
nid.uFlags = NIF_ICON | NIF_MESSAGE | NIF_TIP;
nid.uCallbackMessage = WM_TRAYICON;
nid.hIcon = LoadIcon(NULL, IDI_APPLICATION);
strncpy_s(nid.szTip, "HexUnlocked", sizeof(nid.szTip) - 1);
nid.szTip[sizeof(nid.szTip) - 1] = '\0';
Shell_NotifyIconA(NIM_ADD, &nid);
return true;
}
void TrayIcon::shutdown()
{
if (_hwnd)
{
NOTIFYICONDATAA nid = {0};
nid.cbSize = sizeof(NOTIFYICONDATA);
nid.hWnd = reinterpret_cast<HWND>(_hwnd);
nid.uID = ID_TRAY_APP_ICON;
Shell_NotifyIconA(NIM_DELETE, &nid);
DestroyWindow(reinterpret_cast<HWND>(_hwnd));
UnregisterClassA("HexUnlockedTrayIconClass", GetModuleHandle(NULL));
_hwnd = nullptr;
}
}
void TrayIcon::processMessages()
{
MSG msg;
while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
{
if (msg.message == WM_QUIT)
{
break;
}
TranslateMessage(&msg);
DispatchMessage(&msg);
}
HWND consoleWnd = GetConsoleWindow();
if (consoleWnd && IsIconic(consoleWnd))
{
ShowWindow(consoleWnd, SW_HIDE);
_isConsoleVisible = false;
}
}
void TrayIcon::onToggleConsole()
{
HWND consoleWnd = GetConsoleWindow();
if (!consoleWnd) return;
if (_isConsoleVisible)
{
ShowWindow(consoleWnd, SW_HIDE);
_isConsoleVisible = false;
}
else
{
ShowWindow(consoleWnd, SW_RESTORE);
HWND hCurWnd = GetForegroundWindow();
DWORD dwMyID = GetCurrentThreadId();
DWORD dwCurID = GetWindowThreadProcessId(hCurWnd, NULL);
AttachThreadInput(dwCurID, dwMyID, TRUE);
SetWindowPos(consoleWnd, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE);
SetWindowPos(consoleWnd, HWND_NOTOPMOST, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE);
SetForegroundWindow(consoleWnd);
SetFocus(consoleWnd);
SetActiveWindow(consoleWnd);
AttachThreadInput(dwCurID, dwMyID, FALSE);
_isConsoleVisible = true;
}
}
void TrayIcon::onOpenControlPanel()
{
ShellExecuteA(NULL, "open", "https://dbd.neru.rip", NULL, NULL, SW_SHOWNORMAL);
}
void TrayIcon::onExit()
{
if (_exitCallback) _exitCallback();
}
void TrayIcon::setExitCallback(std::function<void()> callback)
{
_exitCallback = callback;
}
+28
View File
@@ -0,0 +1,28 @@
#pragma once
#include <functional>
class TrayIcon
{
public:
TrayIcon();
~TrayIcon();
bool init();
void shutdown();
void processMessages();
void onToggleConsole();
void onOpenControlPanel();
void onExit();
void setExitCallback(std::function<void()> callback);
private:
static void* windowProc(void* hwnd, unsigned int msg, unsigned long long wParam, long long lParam);
static TrayIcon* instance;
void* _hwnd;
bool _isConsoleVisible;
std::function<void()> _exitCallback;
};
+1 -1
View File
@@ -6,4 +6,4 @@ namespace utils
{ {
std::string getExePath(); std::string getExePath();
std::string randomizeString(size_t length); std::string randomizeString(size_t length);
} } // namespace utils
+7 -1
View File
@@ -3,10 +3,16 @@
#ifndef WIN32_LEAN_AND_MEAN #ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN #define WIN32_LEAN_AND_MEAN
#endif #endif
#ifndef NOMINMAX #ifndef NOMINMAX
#define NOMINMAX #define NOMINMAX
#endif #endif
#if defined(_WIN32) #if defined(_WIN32)
#include <windows.h> #include <minwindef.h>
#include <wtypes.h>
#endif
#ifdef ERROR
#undef ERROR
#endif #endif