mirror of
https://github.com/cemu-project/DS4Windows.git
synced 2024-11-22 17:29:18 +01:00
236 lines
8.5 KiB
C#
236 lines
8.5 KiB
C#
using System;
|
|
using System.Diagnostics;
|
|
using System.Runtime.InteropServices;
|
|
using System.Security;
|
|
using System.Threading.Tasks;
|
|
using System.Text;
|
|
using System.IO;
|
|
|
|
namespace DS4Windows
|
|
{
|
|
[SuppressUnmanagedCodeSecurity]
|
|
class Util
|
|
{
|
|
public enum PROCESS_INFORMATION_CLASS : int
|
|
{
|
|
ProcessBasicInformation = 0,
|
|
ProcessQuotaLimits,
|
|
ProcessIoCounters,
|
|
ProcessVmCounters,
|
|
ProcessTimes,
|
|
ProcessBasePriority,
|
|
ProcessRaisePriority,
|
|
ProcessDebugPort,
|
|
ProcessExceptionPort,
|
|
ProcessAccessToken,
|
|
ProcessLdtInformation,
|
|
ProcessLdtSize,
|
|
ProcessDefaultHardErrorMode,
|
|
ProcessIoPortHandlers,
|
|
ProcessPooledUsageAndLimits,
|
|
ProcessWorkingSetWatch,
|
|
ProcessUserModeIOPL,
|
|
ProcessEnableAlignmentFaultFixup,
|
|
ProcessPriorityClass,
|
|
ProcessWx86Information,
|
|
ProcessHandleCount,
|
|
ProcessAffinityMask,
|
|
ProcessPriorityBoost,
|
|
ProcessDeviceMap,
|
|
ProcessSessionInformation,
|
|
ProcessForegroundInformation,
|
|
ProcessWow64Information,
|
|
ProcessImageFileName,
|
|
ProcessLUIDDeviceMapsEnabled,
|
|
ProcessBreakOnTermination,
|
|
ProcessDebugObjectHandle,
|
|
ProcessDebugFlags,
|
|
ProcessHandleTracing,
|
|
ProcessIoPriority,
|
|
ProcessExecuteFlags,
|
|
ProcessResourceManagement,
|
|
ProcessCookie,
|
|
ProcessImageInformation,
|
|
ProcessCycleTime,
|
|
ProcessPagePriority,
|
|
ProcessInstrumentationCallback,
|
|
ProcessThreadStackAllocation,
|
|
ProcessWorkingSetWatchEx,
|
|
ProcessImageFileNameWin32,
|
|
ProcessImageFileMapping,
|
|
ProcessAffinityUpdateMode,
|
|
ProcessMemoryAllocationMode,
|
|
MaxProcessInfoClass
|
|
}
|
|
|
|
[StructLayout(LayoutKind.Sequential)]
|
|
public class DEV_BROADCAST_DEVICEINTERFACE
|
|
{
|
|
internal Int32 dbcc_size;
|
|
internal Int32 dbcc_devicetype;
|
|
internal Int32 dbcc_reserved;
|
|
internal Guid dbcc_classguid;
|
|
internal Int16 dbcc_name;
|
|
}
|
|
|
|
public const Int32 DBT_DEVTYP_DEVICEINTERFACE = 0x0005;
|
|
|
|
public const Int32 DEVICE_NOTIFY_WINDOW_HANDLE = 0x0000;
|
|
public const Int32 DEVICE_NOTIFY_SERVICE_HANDLE = 0x0001;
|
|
public const Int32 DEVICE_NOTIFY_ALL_INTERFACE_CLASSES = 0x0004;
|
|
|
|
public const Int32 WM_CREATE = 0x0001;
|
|
public const Int32 WM_DEVICECHANGE = 0x0219;
|
|
|
|
public const Int32 DIGCF_PRESENT = 0x0002;
|
|
public const Int32 DIGCF_DEVICEINTERFACE = 0x0010;
|
|
|
|
[DllImport("ntdll.dll", SetLastError = true)]
|
|
public static extern int NtSetInformationProcess(IntPtr processHandle,
|
|
PROCESS_INFORMATION_CLASS processInformationClass, ref IntPtr processInformation, uint processInformationLength);
|
|
|
|
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
|
|
protected static extern IntPtr RegisterDeviceNotification(IntPtr hRecipient, IntPtr NotificationFilter, Int32 Flags);
|
|
|
|
[DllImport("user32.dll", SetLastError = true)]
|
|
protected static extern Boolean UnregisterDeviceNotification(IntPtr Handle);
|
|
|
|
public static Boolean RegisterNotify(IntPtr Form, Guid Class, ref IntPtr Handle, Boolean Window = true)
|
|
{
|
|
IntPtr devBroadcastDeviceInterfaceBuffer = IntPtr.Zero;
|
|
|
|
try
|
|
{
|
|
DEV_BROADCAST_DEVICEINTERFACE devBroadcastDeviceInterface = new DEV_BROADCAST_DEVICEINTERFACE();
|
|
Int32 Size = Marshal.SizeOf(devBroadcastDeviceInterface);
|
|
|
|
devBroadcastDeviceInterface.dbcc_size = Size;
|
|
devBroadcastDeviceInterface.dbcc_devicetype = DBT_DEVTYP_DEVICEINTERFACE;
|
|
devBroadcastDeviceInterface.dbcc_reserved = 0;
|
|
devBroadcastDeviceInterface.dbcc_classguid = Class;
|
|
|
|
devBroadcastDeviceInterfaceBuffer = Marshal.AllocHGlobal(Size);
|
|
Marshal.StructureToPtr(devBroadcastDeviceInterface, devBroadcastDeviceInterfaceBuffer, true);
|
|
|
|
Handle = RegisterDeviceNotification(Form, devBroadcastDeviceInterfaceBuffer, Window ? DEVICE_NOTIFY_WINDOW_HANDLE : DEVICE_NOTIFY_SERVICE_HANDLE);
|
|
|
|
Marshal.PtrToStructure(devBroadcastDeviceInterfaceBuffer, devBroadcastDeviceInterface);
|
|
|
|
return Handle != IntPtr.Zero;
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
Console.WriteLine("{0} {1}", ex.HelpLink, ex.Message);
|
|
throw;
|
|
}
|
|
finally
|
|
{
|
|
if (devBroadcastDeviceInterfaceBuffer != IntPtr.Zero)
|
|
{
|
|
Marshal.FreeHGlobal(devBroadcastDeviceInterfaceBuffer);
|
|
}
|
|
}
|
|
}
|
|
|
|
public static Boolean UnregisterNotify(IntPtr Handle)
|
|
{
|
|
try
|
|
{
|
|
return UnregisterDeviceNotification(Handle);
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
Console.WriteLine("{0} {1}", ex.HelpLink, ex.Message);
|
|
throw;
|
|
}
|
|
}
|
|
|
|
public static void StartProcessHelper(string path)
|
|
{
|
|
if (!Global.IsAdministrator())
|
|
{
|
|
Process.Start(path);
|
|
}
|
|
else
|
|
{
|
|
StartProcessInExplorer(path);
|
|
}
|
|
}
|
|
|
|
public static void StartProcessInExplorer(string path)
|
|
{
|
|
string tmpPath = Path.Combine(Path.GetTempPath(), "urlopener.bat");
|
|
// Create temporary bat script that Explorer will launch
|
|
using (StreamWriter w = new StreamWriter(new FileStream(tmpPath, FileMode.Create, FileAccess.Write)))
|
|
{
|
|
w.WriteLine("@echo off"); // Turn off echo
|
|
w.WriteLine($"@start \"\" /B /MIN \"{path}\""); // Launch URL
|
|
w.WriteLine("@DEL \"%~f0\""); // Attempt to delete myself without opening a time paradox.
|
|
w.Close();
|
|
}
|
|
|
|
ProcessStartInfo startInfo = new ProcessStartInfo();
|
|
startInfo.FileName = "explorer.exe";
|
|
startInfo.Arguments = tmpPath;
|
|
startInfo.WindowStyle = ProcessWindowStyle.Hidden;
|
|
try
|
|
{
|
|
using (Process temp = Process.Start(startInfo)) { }
|
|
}
|
|
catch { }
|
|
}
|
|
|
|
public static void LogAssistBackgroundTask(Task task)
|
|
{
|
|
task.ContinueWith((t) =>
|
|
{
|
|
if (t.IsFaulted)
|
|
{
|
|
AppLogger.LogToGui(t.Exception.ToString(), true);
|
|
}
|
|
});
|
|
}
|
|
|
|
public static int ElevatedCopyUpdater(string tmpUpdaterPath, bool deleteUpdatesDir=false)
|
|
{
|
|
int result = -1;
|
|
string tmpPath = Path.Combine(Path.GetTempPath(), "updatercopy.bat");
|
|
// Create temporary bat script that will later be executed
|
|
using (StreamWriter w = new StreamWriter(new FileStream(tmpPath,
|
|
FileMode.Create, FileAccess.Write)))
|
|
{
|
|
w.WriteLine("@echo off"); // Turn off echo
|
|
w.WriteLine("@echo Attempting to replace updater, please wait...");
|
|
// Move temp downloaded file to destination
|
|
w.WriteLine($"@mov /Y \"{tmpUpdaterPath}\" \"{Global.exedirpath}\\DS4Updater.exe\"");
|
|
if (deleteUpdatesDir)
|
|
{
|
|
w.WriteLine($"@del /S \"{Global.exedirpath}\\Update Files\\DS4Windows\"");
|
|
}
|
|
w.WriteLine("@DEL \"%~f0\""); // Attempt to delete myself without opening a time paradox.
|
|
w.Close();
|
|
}
|
|
|
|
// Execute temp batch script with admin privileges
|
|
ProcessStartInfo startInfo = new ProcessStartInfo();
|
|
startInfo.FileName = tmpPath;
|
|
startInfo.WindowStyle = ProcessWindowStyle.Hidden;
|
|
startInfo.Verb = "runas";
|
|
startInfo.UseShellExecute = true;
|
|
startInfo.CreateNoWindow = true;
|
|
try
|
|
{
|
|
// Launch process, wait and then save exit code
|
|
using (Process temp = Process.Start(startInfo))
|
|
{
|
|
temp.WaitForExit();
|
|
result = temp.ExitCode;
|
|
}
|
|
}
|
|
catch { }
|
|
|
|
return result;
|
|
}
|
|
}
|
|
}
|