|
|
|
@ -0,0 +1,253 @@ |
|
|
|
|
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 = ""; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
} |