You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

253 lines
8.0 KiB

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 = "";
}
}
}