|
|
|
|
using MahApps.Metro.Controls;
|
|
|
|
|
using MahApps.Metro.Controls.Dialogs;
|
|
|
|
|
using System;
|
|
|
|
|
using System.Collections.Generic;
|
|
|
|
|
using System.Diagnostics;
|
|
|
|
|
using System.Linq;
|
|
|
|
|
using System.Runtime.InteropServices;
|
|
|
|
|
using System.Text;
|
|
|
|
|
using System.Threading;
|
|
|
|
|
using System.Threading.Tasks;
|
|
|
|
|
using System.Windows;
|
|
|
|
|
using System.Windows.Controls;
|
|
|
|
|
|
|
|
|
|
namespace GTAOnlineCasinoHelper.Views
|
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
public partial class AutoLobby : UserControl
|
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
[Flags]
|
|
|
|
|
public enum ThreadAccess : int
|
|
|
|
|
{
|
|
|
|
|
TERMINATE = (0x0001),
|
|
|
|
|
SUSPEND_RESUME = (0x0002),
|
|
|
|
|
GET_CONTEXT = (0x0008),
|
|
|
|
|
SET_CONTEXT = (0x0010),
|
|
|
|
|
SET_INFORMATION = (0x0020),
|
|
|
|
|
QUERY_INFORMATION = (0x0040),
|
|
|
|
|
SET_THREAD_TOKEN = (0x0080),
|
|
|
|
|
IMPERSONATE = (0x0100),
|
|
|
|
|
DIRECT_IMPERSONATION = (0x0200)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
[DllImport("kernel32.dll")]
|
|
|
|
|
static extern IntPtr OpenThread(ThreadAccess dwDesiredAccess, bool bInheritHandle, uint dwThreadId);
|
|
|
|
|
[DllImport("kernel32.dll")]
|
|
|
|
|
static extern uint SuspendThread(IntPtr hThread);
|
|
|
|
|
[DllImport("kernel32.dll")]
|
|
|
|
|
static extern int ResumeThread(IntPtr hThread);
|
|
|
|
|
[DllImport("kernel32", CharSet = CharSet.Auto, SetLastError = true)]
|
|
|
|
|
static extern bool CloseHandle(IntPtr handle);
|
|
|
|
|
|
|
|
|
|
private const int SECONDS = 8;
|
|
|
|
|
private const int TIMER_INTERVAL = 50;
|
|
|
|
|
private const string PROCESS_NAME = "GTA5";
|
|
|
|
|
|
|
|
|
|
private int Seconds
|
|
|
|
|
{
|
|
|
|
|
get
|
|
|
|
|
{
|
|
|
|
|
if (CheckBox_OverrideTimeout.IsChecked.HasValue && CheckBox_OverrideTimeout.IsChecked.Value && int.TryParse(TextBox_TimeoutSeconds.Text, out int seconds))
|
|
|
|
|
{
|
|
|
|
|
return seconds;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
return SECONDS;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
private string ProcessName
|
|
|
|
|
{
|
|
|
|
|
get
|
|
|
|
|
{
|
|
|
|
|
return (CheckBox_OverrideProcessName.IsChecked.HasValue && CheckBox_OverrideProcessName.IsChecked.Value) ? TextBox_ProcessName.Text : PROCESS_NAME;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
private bool IsSuspended
|
|
|
|
|
{
|
|
|
|
|
get
|
|
|
|
|
{
|
|
|
|
|
return suspendedProcesses != null && suspendedProcesses.Length > 0;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
private Process[] suspendedProcesses = new Process[0];
|
|
|
|
|
private Timer timer;
|
|
|
|
|
private DateTimeOffset timestamp = DateTimeOffset.MinValue;
|
|
|
|
|
|
|
|
|
|
public AutoLobby()
|
|
|
|
|
{
|
|
|
|
|
this.InitializeComponent();
|
|
|
|
|
this.TextBox_ProcessName.Text = PROCESS_NAME;
|
|
|
|
|
this.TextBox_TimeoutSeconds.Text = SECONDS.ToString();
|
|
|
|
|
this.timer = new Timer(Timer_Tick, this, Timeout.Infinite, TIMER_INTERVAL);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private double GetMilliseconds()
|
|
|
|
|
{
|
|
|
|
|
return DateTime.Now.ToUniversalTime().Subtract(
|
|
|
|
|
new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc)
|
|
|
|
|
).TotalMilliseconds;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void Timer_Tick(object state)
|
|
|
|
|
{
|
|
|
|
|
Dispatcher.Invoke(() =>
|
|
|
|
|
{
|
|
|
|
|
if (!IsSuspended)
|
|
|
|
|
{
|
|
|
|
|
TextBlock_Status.Text = "";
|
|
|
|
|
this.timer.Change(Timeout.Infinite, 50);
|
|
|
|
|
}
|
|
|
|
|
TimeSpan timeSpan = timestamp - DateTimeOffset.Now;
|
|
|
|
|
if (timeSpan.TotalMilliseconds < 0)
|
|
|
|
|
{
|
|
|
|
|
ResumeGTA();
|
|
|
|
|
TextBlock_Status.Text = "";
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
TextBlock_Status.Text = $"{timeSpan.TotalSeconds.ToString("F3")}s";
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void CheckBox_OverrideProcessName_Checked(object sender, RoutedEventArgs e)
|
|
|
|
|
{
|
|
|
|
|
TextBox_ProcessName.Visibility = Visibility.Visible;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void CheckBox_OverrideProcessName_Unchecked(object sender, RoutedEventArgs e)
|
|
|
|
|
{
|
|
|
|
|
TextBox_ProcessName.Visibility = Visibility.Collapsed;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void CheckBox_OverrideTimeout_Checked(object sender, RoutedEventArgs e)
|
|
|
|
|
{
|
|
|
|
|
TextBox_TimeoutSeconds.Visibility = Visibility.Visible;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void CheckBox_OverrideTimeout_Unchecked(object sender, RoutedEventArgs e)
|
|
|
|
|
{
|
|
|
|
|
TextBox_TimeoutSeconds.Visibility = Visibility.Collapsed;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private async void Button_AutoLobby_Click(object sender, RoutedEventArgs e)
|
|
|
|
|
{
|
|
|
|
|
if (IsSuspended)
|
|
|
|
|
{
|
|
|
|
|
await MainWindow.Instance.ShowMessageAsync("GTA V is already suspended", $"GTA V ({ProcessName}.exe) is already suspended");
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
if (!SuspendGTA())
|
|
|
|
|
{
|
|
|
|
|
await MainWindow.Instance.ShowMessageAsync("GTA V is not running", $"GTA V ({ProcessName}.exe) is not running");
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
timestamp = DateTimeOffset.Now + new TimeSpan(0, 0, Seconds);
|
|
|
|
|
TextBlock_Status.Text = $"{Seconds}.000s";
|
|
|
|
|
timer.Change(TIMER_INTERVAL, TIMER_INTERVAL);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private async void Button_Suspend_Click(object sender, RoutedEventArgs e)
|
|
|
|
|
{
|
|
|
|
|
if (IsSuspended)
|
|
|
|
|
{
|
|
|
|
|
await MainWindow.Instance.ShowMessageAsync("GTA V is already suspended", $"GTA V ({ProcessName}.exe) is already suspended");
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
if (!SuspendGTA())
|
|
|
|
|
{
|
|
|
|
|
await MainWindow.Instance.ShowMessageAsync("GTA V is not running", $"GTA V ({ProcessName}.exe) is not running");
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
TextBlock_Status.Text = "Suspended";
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private async void Button_Resume_Click(object sender, RoutedEventArgs e)
|
|
|
|
|
{
|
|
|
|
|
if (!IsSuspended)
|
|
|
|
|
{
|
|
|
|
|
await MainWindow.Instance.ShowMessageAsync("GTA V is not suspended", $"GTA V ({ProcessName}.exe) is not suspended");
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
ResumeGTA();
|
|
|
|
|
TextBlock_Status.Text = "";
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private static void SuspendProcess(int pid)
|
|
|
|
|
{
|
|
|
|
|
var process = Process.GetProcessById(pid);
|
|
|
|
|
|
|
|
|
|
if (process.ProcessName == string.Empty)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
foreach (ProcessThread pT in process.Threads)
|
|
|
|
|
{
|
|
|
|
|
IntPtr pOpenThread = OpenThread(ThreadAccess.SUSPEND_RESUME, false, (uint)pT.Id);
|
|
|
|
|
|
|
|
|
|
if (pOpenThread == IntPtr.Zero)
|
|
|
|
|
{
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
SuspendThread(pOpenThread);
|
|
|
|
|
|
|
|
|
|
CloseHandle(pOpenThread);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public static void ResumeProcess(int pid)
|
|
|
|
|
{
|
|
|
|
|
var process = Process.GetProcessById(pid);
|
|
|
|
|
|
|
|
|
|
if (process.ProcessName == string.Empty)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
foreach (ProcessThread pT in process.Threads)
|
|
|
|
|
{
|
|
|
|
|
IntPtr pOpenThread = OpenThread(ThreadAccess.SUSPEND_RESUME, false, (uint)pT.Id);
|
|
|
|
|
|
|
|
|
|
if (pOpenThread == IntPtr.Zero)
|
|
|
|
|
{
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var suspendCount = 0;
|
|
|
|
|
do
|
|
|
|
|
{
|
|
|
|
|
suspendCount = ResumeThread(pOpenThread);
|
|
|
|
|
} while (suspendCount > 0);
|
|
|
|
|
|
|
|
|
|
CloseHandle(pOpenThread);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private bool SuspendGTA()
|
|
|
|
|
{
|
|
|
|
|
suspendedProcesses = Process.GetProcessesByName(ProcessName);
|
|
|
|
|
if (suspendedProcesses.Length < 1)
|
|
|
|
|
{
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
foreach (Process process in suspendedProcesses)
|
|
|
|
|
{
|
|
|
|
|
SuspendProcess(process.Id);
|
|
|
|
|
}
|
|
|
|
|
//labelState.Text = "Suspended";
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void ResumeGTA()
|
|
|
|
|
{
|
|
|
|
|
timer.Change(Timeout.Infinite, TIMER_INTERVAL);
|
|
|
|
|
foreach (var process in suspendedProcesses)
|
|
|
|
|
{
|
|
|
|
|
ResumeProcess(process.Id);
|
|
|
|
|
}
|
|
|
|
|
suspendedProcesses = new Process[0];
|
|
|
|
|
TextBlock_Status.Text = "";
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|