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