Files
hrynco-kswitcher/src/main.cpp
T

110 lines
3.7 KiB
C++

#include "app.h"
#include <shellapi.h>
#include <shlobj.h>
#include "configuration.h"
int WINAPI wWinMain(HINSTANCE instance, HINSTANCE, PWSTR, int)
{
CoInitializeEx(nullptr, COINIT_APARTMENTTHREADED);
int argc{};
auto argv = CommandLineToArgvW(GetCommandLineW(), &argc);
std::wstring arg = argc > 1 ? argv[1] : L"";
if (argc == 2 && arg.starts_with(L"--history-host=")) {
LocalFree(argv);
int result = 1;
try {
auto service = reinterpret_cast<HWND>(uintptr_t(std::stoull(arg.substr(15))));
wchar_t name[64]{}; GetClassNameW(service, name, 64);
if (std::wstring(name) != L"KSwitcher.Main" || !ks::configurationPeer(service, L"KSwitcher.exe"))
throw std::runtime_error("Invalid history service");
ks::App app(instance, true, {}, service);
result = app.execute();
} catch (...) {}
CoUninitialize();
return result;
}
if (arg.starts_with(L"--configure-autostart="))
{
int result = 1;
try
{
if (argc != 3 || ks::currentUserSid() != argv[2] || !IsUserAnAdmin())
throw std::runtime_error("Administrator approval for the same Windows account is required");
if (arg != L"--configure-autostart=0" && arg != L"--configure-autostart=1" &&
arg != L"--configure-autostart=2")
throw std::runtime_error("Invalid autostart mode");
ks::configureAutostart(arg.back() - L'0');
result = 0;
}
catch (const std::exception &e)
{
MessageBoxW(nullptr, ks::wide(e.what()).c_str(), L"KSwitcher autostart", MB_OK | MB_ICONERROR);
}
LocalFree(argv);
CoUninitialize();
return result;
}
HANDLE mutex = CreateMutexW(nullptr, TRUE, L"Local\\KSwitcher.Native.Singleton");
bool existing = GetLastError() == ERROR_ALREADY_EXISTS;
int cmd = ks::ShowHistory;
if (arg == L"--capture")
cmd = ks::Screenshot;
else if (arg == L"--convert")
cmd = ks::Toggle;
else if (arg == L"--case")
cmd = ks::Case;
else if (arg == L"--transliterate")
cmd = ks::Translit;
else if (arg == L"--settings")
cmd = 20;
else if (arg == L"--snippets")
cmd = 21;
else if (arg == L"--exit")
cmd = 99;
else if (arg == L"--check-update")
cmd = 23;
LocalFree(argv);
if (existing)
{
HWND window = FindWindowW(L"KSwitcher.Main", L"KSwitcher");
if (window)
{
if (cmd == 23) { DWORD pid{}; GetWindowThreadProcessId(window, &pid); AllowSetForegroundWindow(pid); }
COPYDATASTRUCT data{1, sizeof(cmd), &cmd};
DWORD_PTR result{};
SendMessageTimeoutW(window, WM_COPYDATA, 0, (LPARAM)&data, SMTO_ABORTIFHUNG, 1000, &result);
}
CloseHandle(mutex);
CoUninitialize();
return 0;
}
if (arg == L"--exit")
{
CloseHandle(mutex);
CoUninitialize();
return 0;
}
int result = 0;
try
{
ks::App app(instance, arg == L"--smoke-test");
app.isolateHistory = !app.smoke;
if (arg.starts_with(L"--update-ready-event="))
app.updateStartupEvent = arg.substr(std::wstring(L"--update-ready-event=").size());
else if (!arg.empty() && arg != L"--smoke-test")
app.startCommand = cmd;
result = app.execute();
}
catch (const std::exception &e)
{
MessageBoxW(nullptr, ks::wide(e.what()).c_str(), L"KSwitcher could not start", MB_OK | MB_ICONERROR);
result = 1;
}
if (mutex)
{
ReleaseMutex(mutex);
CloseHandle(mutex);
}
CoUninitialize();
return result;
}