From 5b91d1ae1c958af67429a7702d691ce004083de4 Mon Sep 17 00:00:00 2001 From: Ignefolio Date: Tue, 18 Jun 2019 20:56:16 +0200 Subject: [PATCH 1/2] Should make the detection better. --- XboxKeyboardMouse/UWPUtils.cs | 143 ++++++++++++++++++ .../XboxController/Emulation/XboxStream.cs | 97 ++++-------- XboxKeyboardMouse/XboxKeyboardMouse.csproj | 1 + 3 files changed, 171 insertions(+), 70 deletions(-) create mode 100644 XboxKeyboardMouse/UWPUtils.cs diff --git a/XboxKeyboardMouse/UWPUtils.cs b/XboxKeyboardMouse/UWPUtils.cs new file mode 100644 index 0000000..8e6aeb4 --- /dev/null +++ b/XboxKeyboardMouse/UWPUtils.cs @@ -0,0 +1,143 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Runtime.InteropServices; +using System.Text; +using System.Threading.Tasks; + +namespace XboxKeyboardMouse +{ + internal struct WINDOWINFO + { + public uint ownerpid; + public uint childpid; + } + + public class UWPUtils + { + #region User32 + [DllImport("user32.dll")] + public static extern IntPtr GetForegroundWindow(); + [DllImport("user32.dll", SetLastError = true)] + public static extern uint GetWindowThreadProcessId(IntPtr hWnd, out uint lpdwProcessId); + + /// + /// Delegate for the EnumChildWindows method + /// + /// Window handle + /// Caller-defined variable; we use it for a pointer to our list + /// True to continue enumerating, false to bail. + public delegate bool EnumWindowProc(IntPtr hWnd, IntPtr parameter); + + [DllImport("user32", SetLastError = true)] + [return: MarshalAs(UnmanagedType.Bool)] + public static extern bool EnumChildWindows(IntPtr hWndParent, EnumWindowProc lpEnumFunc, IntPtr lParam); + #endregion + + #region Kernel32 + public const UInt32 PROCESS_QUERY_INFORMATION = 0x400; + public const UInt32 PROCESS_VM_READ = 0x010; + + [DllImport("kernel32.dll", SetLastError = true)] + public static extern bool QueryFullProcessImageName([In]IntPtr hProcess, [In]int dwFlags, [Out]StringBuilder lpExeName, ref int lpdwSize); + + [DllImport("kernel32.dll", SetLastError = true)] + public static extern IntPtr OpenProcess( + UInt32 dwDesiredAccess, + [MarshalAs(UnmanagedType.Bool)] + Boolean bInheritHandle, + Int32 dwProcessId + ); + #endregion + + public static string GetProcessName(IntPtr hWnd) + { + string processName = null; + + hWnd = GetForegroundWindow(); + + if (hWnd == IntPtr.Zero) + return null; + + uint pID; + GetWindowThreadProcessId(hWnd, out pID); + + IntPtr proc; + if ((proc = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, false, (int)pID)) == IntPtr.Zero) + return null; + + int capacity = 2000; + StringBuilder sb = new StringBuilder(capacity); + QueryFullProcessImageName(proc, 0, sb, ref capacity); + + processName = sb.ToString(0, capacity); + + // UWP apps are wrapped in another app called, if this has focus then try and find the child UWP process + if (Path.GetFileName(processName).Equals("ApplicationFrameHost.exe")) + { + processName = UWP_AppName(hWnd, pID); + } + + return processName; + } + + #region Get UWP Application Name + + /// + /// Find child process for uwp apps, edge, mail, etc. + /// + /// hWnd + /// pID + /// The application name of the UWP. + private static string UWP_AppName(IntPtr hWnd, uint pID) + { + WINDOWINFO windowinfo = new WINDOWINFO(); + windowinfo.ownerpid = pID; + windowinfo.childpid = windowinfo.ownerpid; + + IntPtr pWindowinfo = Marshal.AllocHGlobal(Marshal.SizeOf(windowinfo)); + + Marshal.StructureToPtr(windowinfo, pWindowinfo, false); + + EnumWindowProc lpEnumFunc = new EnumWindowProc(EnumChildWindowsCallback); + EnumChildWindows(hWnd, lpEnumFunc, pWindowinfo); + + windowinfo = (WINDOWINFO)Marshal.PtrToStructure(pWindowinfo, typeof(WINDOWINFO)); + + IntPtr proc; + if ((proc = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, false, (int)windowinfo.childpid)) == IntPtr.Zero) + return null; + + int capacity = 2000; + StringBuilder sb = new StringBuilder(capacity); + QueryFullProcessImageName(proc, 0, sb, ref capacity); + + Marshal.FreeHGlobal(pWindowinfo); + + return sb.ToString(0, capacity); + } + + /// + /// Callback for enumerating the child windows. + /// + /// hWnd + /// lParam + /// always true. + private static bool EnumChildWindowsCallback(IntPtr hWnd, IntPtr lParam) + { + WINDOWINFO info = (WINDOWINFO)Marshal.PtrToStructure(lParam, typeof(WINDOWINFO)); + + uint pID; + GetWindowThreadProcessId(hWnd, out pID); + + if (pID != info.ownerpid) + info.childpid = pID; + + Marshal.StructureToPtr(info, lParam, true); + + return true; + } + #endregion + } +} diff --git a/XboxKeyboardMouse/XboxController/Emulation/XboxStream.cs b/XboxKeyboardMouse/XboxController/Emulation/XboxStream.cs index b7b2fbd..336e3ba 100644 --- a/XboxKeyboardMouse/XboxController/Emulation/XboxStream.cs +++ b/XboxKeyboardMouse/XboxController/Emulation/XboxStream.cs @@ -8,18 +8,17 @@ namespace XboxKeyboardMouse { - class XboxStream { + class XboxStream + { [DllImport("user32.dll")] private static extern IntPtr GetForegroundWindow(); - [DllImport("user32.dll")] - private static extern int GetWindowText(IntPtr hWnd, StringBuilder lpString, int nMaxCount); - [DllImport("user32.dll")] private static extern bool GetWindowRect(IntPtr hWnd, out RECT Rect); [StructLayout(LayoutKind.Sequential)] - public struct RECT { + public struct RECT + { public int X; //left public int Y; //top public int Width; //right @@ -29,54 +28,8 @@ public struct RECT { public static Thread tMouseMovement; - private static readonly string[] defaultAppNames = { - "Xbox", - "Xbox Console Companion", - "Xbox Console Companion - Beta", - "Xbox Companion-console", - "Xbox Companion-console - bèta", - "Xbox-konsol Companion", - "Xbox-konsol Companion - beta", - "Xbox konsoles palīgs", - "Xbox Konsolu Yardımcısı", - "Xbox Konsolu Yardımcısı - Beta", - "Xbox 主機小幫手", - "Xbox 主機小幫手 - beta 搶鮮版", - "Xbox 本体コンパニオン", - "Xbox 本体コンパニオン - ベータ", - "Xbox 본체 도우미", - "Xbox 본체 도우미 - 베타 버전", - "Xboxi konsooliabiline", - "Xboxi konsooliabiline - beetaversioon", - "„Xbox“ konsolės pagalbinė priemonė", - "„Xbox“ konsolės pagalbinė priemonė - beta versija", - "Compagnon de la console Xbox", - "Compagnon de la console Xbox - bêta", - "Compañero de la consola Xbox", - "Compañero de la consola Xbox - beta", - "Complemento da Consola Xbox", - "Complemento da Consola Xbox - beta", - "Companion console Xbox", - "Companion console Xbox - beta", - "Компаньон консоли Xbox", - "Компаньон консоли Xbox - бета-версия", - "Pomoćnik konzole Xbox", - "Pomoćnik konzole Xbox - beta-verzija", - "Pomocnik konsoli Xbox", - "Pomocnik konsoli Xbox - wersja Beta", - "Spremljevalec za konzolo Xbox", - "Spremljevalec za konzolo Xbox - beta", - "Teman Konsol Xbox", - "Teman Konsol Xbox - beta", - "Ứng dụng Đồng hành Bảng điều khiển Xbox", - "Ứng dụng Đồng hành Bảng điều khiển Xbox - beta", - "مصاحب وحدة تحكم Xbox", - "مصاحب وحدة تحكم Xbox - إصدار تجريبي", - "מסייע קונסולת Xbox", - "מסייע קונסולת Xbox - בתא", - }; - - public static void XboxAppDetector() { + public static void XboxAppDetector() + { bool started = false; const int count = 512; @@ -88,20 +41,20 @@ public static void XboxAppDetector() { Thread.Sleep(500); IntPtr handle = GetForegroundWindow(); - if (GetWindowText(handle, text, count) > 0) + + var name = UWPUtils.GetProcessName(handle); + + if (!name.EndsWith("XboxApp.exe") && started) { - if (!defaultAppNames.Contains(text.ToString())) - { - ShowAndFreeCursor(); - started = false; - Program.MainForm.StatusWaiting(); - } - else if (!started) - { - LockAndHideCursor(); - started = true; - Program.MainForm.StatusRunning(); - } + ShowAndFreeCursor(); + started = false; + Program.MainForm.StatusWaiting(); + } + if (name.EndsWith("XboxApp.exe") && !started) + { + LockAndHideCursor(); + started = true; + Program.MainForm.StatusRunning(); } } } @@ -111,7 +64,8 @@ public static void XboxAppDetector() { } } - private static void LockAndHideCursor() { + private static void LockAndHideCursor() + { if (Program.HideCursor) CursorView.CursorHide(); @@ -121,14 +75,16 @@ private static void LockAndHideCursor() { tMouseMovement.Start(); } - private static void ShowAndFreeCursor() { + private static void ShowAndFreeCursor() + { CursorView.CursorShow(); if (tMouseMovement != null) tMouseMovement.Abort(); } - private static bool IsFullscreen(IntPtr handle) { + private static bool IsFullscreen(IntPtr handle) + { bool runningFullScreen = false; RECT appBounds; Rectangle screenBounds; @@ -136,7 +92,8 @@ private static bool IsFullscreen(IntPtr handle) { GetWindowRect(handle, out appBounds); screenBounds = Screen.FromHandle(handle).Bounds; - if ((appBounds.Height - appBounds.Y) == screenBounds.Height && (appBounds.Width - appBounds.X) == screenBounds.Width) { + if ((appBounds.Height - appBounds.Y) == screenBounds.Height && (appBounds.Width - appBounds.X) == screenBounds.Width) + { runningFullScreen = true; } diff --git a/XboxKeyboardMouse/XboxKeyboardMouse.csproj b/XboxKeyboardMouse/XboxKeyboardMouse.csproj index 37792c4..923951a 100644 --- a/XboxKeyboardMouse/XboxKeyboardMouse.csproj +++ b/XboxKeyboardMouse/XboxKeyboardMouse.csproj @@ -143,6 +143,7 @@ True Resources.resx + Form From 62155ffc796ffb976f4e8499cc74fc3646aaa6ee Mon Sep 17 00:00:00 2001 From: Ignefolio Date: Wed, 19 Jun 2019 17:23:50 +0200 Subject: [PATCH 2/2] added xml comment to GetProccessName --- XboxKeyboardMouse/UWPUtils.cs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/XboxKeyboardMouse/UWPUtils.cs b/XboxKeyboardMouse/UWPUtils.cs index 8e6aeb4..b5e3fee 100644 --- a/XboxKeyboardMouse/UWPUtils.cs +++ b/XboxKeyboardMouse/UWPUtils.cs @@ -51,6 +51,11 @@ Int32 dwProcessId ); #endregion + /// + /// Gets the path of application running in foreground + /// + /// Window handle + /// Path of the application public static string GetProcessName(IntPtr hWnd) { string processName = null;