private void CheckOptions(ArgumentParser parser) { if (parser.HasErrors) { runShutdown = false; exitApp = true; Current.Shutdown(1); } else if (parser.Driverinstall) { CreateBaseThread(); DS4Forms.WelcomeDialog dialog = new DS4Forms.WelcomeDialog(true); dialog.ShowDialog(); runShutdown = false; exitApp = true; Current.Shutdown(); } else if (parser.ReenableDevice) { DS4Windows.DS4Devices.reEnableDevice(parser.DeviceInstanceId); runShutdown = false; exitApp = true; Current.Shutdown(); } else if (parser.Runtask) { StartupMethods.LaunchOldTask(); runShutdown = false; exitApp = true; Current.Shutdown(); } else if (parser.Command) { IntPtr hWndDS4WindowsForm = IntPtr.Zero; hWndDS4WindowsForm = FindWindow(ReadIPCClassNameMMF(), "DS4Windows"); if (hWndDS4WindowsForm != IntPtr.Zero) { COPYDATASTRUCT cds; cds.lpData = IntPtr.Zero; try { cds.dwData = IntPtr.Zero; cds.cbData = parser.CommandArgs.Length; cds.lpData = Marshal.StringToHGlobalAnsi(parser.CommandArgs); SendMessage(hWndDS4WindowsForm, DS4Forms.MainWindow.WM_COPYDATA, IntPtr.Zero, ref cds); } finally { if (cds.lpData != IntPtr.Zero) { Marshal.FreeHGlobal(cds.lpData); } } } runShutdown = false; exitApp = true; Current.Shutdown(); } }
private void Application_Startup(object sender, StartupEventArgs e) { runShutdown = true; skipSave = true; ArgumentParser parser = new ArgumentParser(); parser.Parse(e.Args); CheckOptions(parser); if (exitApp) { return; } try { Process.GetCurrentProcess().PriorityClass = ProcessPriorityClass.High; } catch { } // Ignore problems raising the priority. // Force Normal IO Priority IntPtr ioPrio = new IntPtr(2); DS4Windows.Util.NtSetInformationProcess(Process.GetCurrentProcess().Handle, DS4Windows.Util.PROCESS_INFORMATION_CLASS.ProcessIoPriority, ref ioPrio, 4); // Force Normal Page Priority IntPtr pagePrio = new IntPtr(5); DS4Windows.Util.NtSetInformationProcess(Process.GetCurrentProcess().Handle, DS4Windows.Util.PROCESS_INFORMATION_CLASS.ProcessPagePriority, ref pagePrio, 4); try { // another instance is already running if OpenExisting succeeds. threadComEvent = EventWaitHandle.OpenExisting(SingleAppComEventName, System.Security.AccessControl.EventWaitHandleRights.Synchronize | System.Security.AccessControl.EventWaitHandleRights.Modify); threadComEvent.Set(); // signal the other instance. threadComEvent.Close(); Current.Shutdown(); // Quit temp instance return; } catch { /* don't care about errors */ } // Create the Event handle threadComEvent = new EventWaitHandle(false, EventResetMode.ManualReset, SingleAppComEventName); CreateTempWorkerThread(); CreateControlService(); DS4Windows.Global.FindConfigLocation(); bool firstRun = DS4Windows.Global.firstRun; if (firstRun) { DS4Forms.SaveWhere savewh = new DS4Forms.SaveWhere(false); savewh.ShowDialog(); } DS4Windows.Global.Load(); if (!CreateConfDirSkeleton()) { MessageBox.Show($"Cannot create config folder structure in {DS4Windows.Global.appdatapath}. Exiting", "DS4Windows", MessageBoxButton.OK, MessageBoxImage.Error); Current.Shutdown(1); } logHolder = new LoggerHolder(rootHub); DispatcherUnhandledException += App_DispatcherUnhandledException; Logger logger = logHolder.Logger; string version = DS4Windows.Global.exeversion; logger.Info($"DS4Windows version {version}"); //logger.Info("DS4Windows version 2.0"); logger.Info("Logger created"); //DS4Windows.Global.ProfilePath[0] = "mixed"; //DS4Windows.Global.LoadProfile(0, false, rootHub, false, false); if (firstRun) { logger.Info("No config found. Creating default config"); //Directory.CreateDirectory(DS4Windows.Global.appdatapath); AttemptSave(); //Directory.CreateDirectory(DS4Windows.Global.appdatapath + @"\Profiles\"); //Directory.CreateDirectory(DS4Windows.Global.appdatapath + @"\Macros\"); DS4Windows.Global.SaveProfile(0, "Default"); DS4Windows.Global.ProfilePath[0] = DS4Windows.Global.OlderProfilePath[0] = "Default"; /*DS4Windows.Global.ProfilePath[1] = DS4Windows.Global.OlderProfilePath[1] = "Default"; * DS4Windows.Global.ProfilePath[2] = DS4Windows.Global.OlderProfilePath[2] = "Default"; * DS4Windows.Global.ProfilePath[3] = DS4Windows.Global.OlderProfilePath[3] = "Default"; */ logger.Info("Default config created"); } skipSave = false; if (!DS4Windows.Global.LoadActions()) { DS4Windows.Global.CreateStdActions(); } SetUICulture(DS4Windows.Global.UseLang); DS4Forms.MainWindow window = new DS4Forms.MainWindow(parser); MainWindow = window; window.Show(); window.CheckMinStatus(); HwndSource source = PresentationSource.FromVisual(window) as HwndSource; CreateIPCClassNameMMF(source.Handle); }
private void CheckOptions(ArgumentParser parser) { if (parser.HasErrors) { runShutdown = false; exitApp = true; Current.Shutdown(1); } else if (parser.Driverinstall) { CreateBaseThread(); DS4Forms.WelcomeDialog dialog = new DS4Forms.WelcomeDialog(true); dialog.ShowDialog(); runShutdown = false; exitApp = true; Current.Shutdown(); } else if (parser.ReenableDevice) { DS4Windows.DS4Devices.reEnableDevice(parser.DeviceInstanceId); runShutdown = false; exitApp = true; Current.Shutdown(); } else if (parser.Runtask) { StartupMethods.LaunchOldTask(); runShutdown = false; exitApp = true; Current.Shutdown(); } else if (parser.Command) { IntPtr hWndDS4WindowsForm = IntPtr.Zero; hWndDS4WindowsForm = FindWindow(ReadIPCClassNameMMF(), "DS4Windows"); if (hWndDS4WindowsForm != IntPtr.Zero) { bool bDoSendMsg = true; bool bWaitResultData = false; bool bOwnsMutex = false; Mutex ipcSingleTaskMutex = null; EventWaitHandle ipcNotifyEvent = null; COPYDATASTRUCT cds; cds.lpData = IntPtr.Zero; try { if (parser.CommandArgs.ToLower().StartsWith("query.")) { // Query.device# (1..4) command returns a string result via memory mapped file. The cmd is sent to the background DS4Windows // process (via WM_COPYDATA wnd msg), then this client process waits for the availability of the result and prints it to console output pipe. // Use mutex obj to make sure that concurrent client calls won't try to write and read the same MMF result file at the same time. ipcSingleTaskMutex = new Mutex(false, "DS4Windows_IPCResultData_SingleTaskMtx"); try { bOwnsMutex = ipcSingleTaskMutex.WaitOne(10000); } catch (AbandonedMutexException) { bOwnsMutex = true; } if (bOwnsMutex) { // This process owns the inter-process sync mutex obj. Let's proceed with creating the output MMF file and waiting for a result. bWaitResultData = true; CreateIPCResultDataMMF(); ipcNotifyEvent = new EventWaitHandle(false, EventResetMode.AutoReset, "DS4Windows_IPCResultData_ReadyEvent"); } else { // If the mtx failed then something must be seriously wrong. Cannot do anything in that case because MMF file may be modified by concurrent processes. bDoSendMsg = false; } } if (bDoSendMsg) { cds.dwData = IntPtr.Zero; cds.cbData = parser.CommandArgs.Length; cds.lpData = Marshal.StringToHGlobalAnsi(parser.CommandArgs); SendMessage(hWndDS4WindowsForm, DS4Forms.MainWindow.WM_COPYDATA, IntPtr.Zero, ref cds); if (bWaitResultData) { Console.WriteLine(WaitAndReadIPCResultDataMMF(ipcNotifyEvent)); } } } finally { // Release the result MMF file in the client process before releasing the mtx and letting other client process to proceed with the same MMF file if (ipcResultDataMMA != null) { ipcResultDataMMA.Dispose(); } if (ipcResultDataMMF != null) { ipcResultDataMMF.Dispose(); } ipcResultDataMMA = null; ipcResultDataMMF = null; // If this was "Query.xxx" cmdline client call then release the inter-process mutex and let other concurrent clients to proceed (if there are anyone waiting for the MMF result file) if (bOwnsMutex && ipcSingleTaskMutex != null) { ipcSingleTaskMutex.ReleaseMutex(); } if (cds.lpData != IntPtr.Zero) { Marshal.FreeHGlobal(cds.lpData); } } } runShutdown = false; exitApp = true; Current.Shutdown(); } }