using System; using System.Runtime.InteropServices; using System.Diagnostics; /// /// /// public class WindowsAPI { /// /// /// public const uint WM_KEYDOWN = 0x100; /// /// /// public const uint WM_KEYUP = 0x101; /// /// /// public const uint WM_LBUTTONDOWN = 0x201; /// /// /// public const uint WM_LBUTTONUP = 0x202; public const uint WM_CHAR = 0x102; /// /// /// public const int MK_LBUTTON = 0x01; /// /// /// public const int VK_RETURN = 0x0d; public const int VK_ESCAPE = 0x1b; /// /// /// public const int VK_TAB = 0x09; /// /// /// public const int VK_LEFT = 0x25; /// /// /// public const int VK_UP = 0x26; /// /// /// public const int VK_RIGHT = 0x27; /// /// /// public const int VK_DOWN = 0x28; /// /// /// public const int VK_F5 = 0x74; /// /// /// public const int VK_F6 = 0x75; /// /// /// public const int VK_F7 = 0x76; /// /// The GetForegroundWindow function returns a handle to the foreground window. /// [DllImport("user32.dll")] public static extern IntPtr GetForegroundWindow(); [DllImport("kernel32.dll")] public static extern uint GetCurrentThreadId(); [DllImport("user32.dll", SetLastError = true)] public static extern uint GetWindowThreadProcessId(IntPtr hWnd, out uint lpdwProcessId); [DllImport("user32.dll")] public static extern bool AttachThreadInput(uint idAttach, uint idAttachTo, bool fAttach); [DllImport("kernel32.dll", SetLastError = true)] public static extern bool ReadProcessMemory( IntPtr hProcess, IntPtr lpBaseAddress, [Out()] byte[] lpBuffer, int dwSize, out int lpNumberOfBytesRead ); public static void SwitchWindow(IntPtr windowHandle) { if (GetForegroundWindow() == windowHandle) return; IntPtr foregroundWindowHandle = GetForegroundWindow(); uint currentThreadId = GetCurrentThreadId(); uint temp; uint foregroundThreadId = GetWindowThreadProcessId(foregroundWindowHandle, out temp); AttachThreadInput(currentThreadId, foregroundThreadId, true); SetForegroundWindow(windowHandle); AttachThreadInput(currentThreadId, foregroundThreadId, false); while (GetForegroundWindow() != windowHandle) { } } /// /// /// /// /// /// /// /// [DllImport("user32.dll", SetLastError = true)] public static extern IntPtr FindWindowEx(IntPtr hwndParent, IntPtr hwndChildAfter, string lpszClass, string lpszWindow); /// /// /// /// /// /// /// /// [DllImport("User32.Dll", EntryPoint = "PostMessageA")] public static extern bool PostMessage(IntPtr hWnd, uint msg, int wParam, int lParam); /// /// /// /// /// [DllImport("user32.dll")] public static extern byte VkKeyScan(char ch); [DllImport("user32.dll")] public static extern uint MapVirtualKey(uint uCode, uint uMapType); /// /// /// /// /// public static IntPtr FindWindow(string name) { Process[] procs = Process.GetProcesses(); foreach (Process proc in procs) { if (proc.MainWindowTitle == name) { return proc.MainWindowHandle; } } return IntPtr.Zero; } public static void Main() { int procesId = YourEnumerateClass.Enum16BitProcesses(); Process processes = Process.GetProcessById( procesId ); if (processes == null) throw new Exception("Could not find the Warhammer process; is Warhammer running?"); IntPtr WindowHandle = processes.MainWindowHandle; PressKey('a', true); System.Threading.Thread.Sleep(100); PressKey('a', false); } [DllImport("user32.dll")] public static extern IntPtr SetFocus(IntPtr hWnd); [DllImport("user32.dll")] [return: MarshalAs(UnmanagedType.Bool)] public static extern bool SetForegroundWindow(IntPtr hWnd); /// /// /// /// /// /// public static int MakeLong(int low, int high) { return (high << 16) | (low & 0xffff); } public static void KeyDown(ushort scanCode) { INPUT[] inputs = new INPUT[1]; inputs[0].type = WindowsAPI.INPUT_KEYBOARD; inputs[0].ki.dwFlags = 0; inputs[0].ki.wScan = (ushort)(scanCode & 0xff); uint intReturn = WindowsAPI.SendInput(1, inputs, System.Runtime.InteropServices.Marshal.SizeOf(inputs[0])); if (intReturn != 1) { throw new Exception("Could not send key: " + scanCode); } } public static void KeyUp(ushort scanCode) { INPUT[] inputs = new INPUT[1]; inputs[0].type = WindowsAPI.INPUT_KEYBOARD; inputs[0].ki.wScan = scanCode; inputs[0].ki.dwFlags = WindowsAPI.KEYEVENTF_KEYUP; uint intReturn = WindowsAPI.SendInput(1, inputs, System.Runtime.InteropServices.Marshal.SizeOf(inputs[0])); if (intReturn != 1) { throw new Exception("Could not send key: " + scanCode); } } public static void PressKey(char ch, bool press) { byte vk = WindowsAPI.VkKeyScan(ch); ushort scanCode = (ushort)WindowsAPI.MapVirtualKey(vk, 0); if (press) KeyDown(scanCode); else KeyUp(scanCode); } [DllImport("User32.dll")] public static extern uint SendInput(uint numberOfInputs, [MarshalAs(UnmanagedType.LPArray, SizeConst = 1)] INPUT[] input, int structSize); [DllImport("user32.dll")] public static extern IntPtr GetMessageExtraInfo(); public const int INPUT_MOUSE = 0; public const int INPUT_KEYBOARD = 1; public const int INPUT_HARDWARE = 2; public const uint KEYEVENTF_EXTENDEDKEY = 0x0001; public const uint KEYEVENTF_KEYUP = 0x0002; public const uint KEYEVENTF_UNICODE = 0x0004; public const uint KEYEVENTF_SCANCODE = 0x0008; public const uint XBUTTON1 = 0x0001; public const uint XBUTTON2 = 0x0002; public const uint MOUSEEVENTF_MOVE = 0x0001; public const uint MOUSEEVENTF_LEFTDOWN = 0x0002; public const uint MOUSEEVENTF_LEFTUP = 0x0004; public const uint MOUSEEVENTF_RIGHTDOWN = 0x0008; public const uint MOUSEEVENTF_RIGHTUP = 0x0010; public const uint MOUSEEVENTF_MIDDLEDOWN = 0x0020; public const uint MOUSEEVENTF_MIDDLEUP = 0x0040; public const uint MOUSEEVENTF_XDOWN = 0x0080; public const uint MOUSEEVENTF_XUP = 0x0100; public const uint MOUSEEVENTF_WHEEL = 0x0800; public const uint MOUSEEVENTF_VIRTUALDESK = 0x4000; public const uint MOUSEEVENTF_ABSOLUTE = 0x8000; } [StructLayout(LayoutKind.Sequential)] public struct MOUSEINPUT { int dx; int dy; uint mouseData; uint dwFlags; uint time; IntPtr dwExtraInfo; } [StructLayout(LayoutKind.Sequential)] public struct KEYBDINPUT { public ushort wVk; public ushort wScan; public uint dwFlags; public uint time; public IntPtr dwExtraInfo; } [StructLayout(LayoutKind.Sequential)] public struct HARDWAREINPUT { uint uMsg; ushort wParamL; ushort wParamH; } [StructLayout(LayoutKind.Explicit)] public struct INPUT { [FieldOffset(0)] public int type; [FieldOffset(4)] //* public MOUSEINPUT mi; [FieldOffset(4)] //* public KEYBDINPUT ki; [FieldOffset(4)] //* public HARDWAREINPUT hi; } public class YourEnumerateClass { public static void Enum16BitProcesses() { // create a delegate for the callback function ProcessTasksExDelegate procTasksDlgt = new ProcessTasksExDelegate(YourEnumerateClass.ProcessTasksEx); // this part is the easy way of getting NTVDM procs foreach (var ntvdm in Process.GetProcessesByName("ntvdm")) { Console.WriteLine("ntvdm id = {0}", ntvdm.Id); int apiRet = VDMEnumTaskWOWEx(ntvdm.Id, procTasksDlgt, IntPtr.Zero); Console.WriteLine("EnumTaskWOW returns {0}", apiRet); } } // declaration of API function callback public delegate bool ProcessTasksExDelegate( int ThreadId, IntPtr hMod16, IntPtr hTask16, IntPtr ptrModName, IntPtr ptrFileName, IntPtr UserDefined ); // the actual function that fails on Vista so far [DllImport("VdmDbg.dll", SetLastError = false, CharSet = CharSet.Auto)] public static extern int VDMEnumTaskWOWEx( int processId, ProcessTasksExDelegate TaskEnumProc, IntPtr lparam); // the actual callback function, on Vista never gets called public static bool ProcessTasksEx( int ThreadId, IntPtr hMod16, IntPtr hTask16, IntPtr ptrModName, IntPtr ptrFileName, IntPtr UserDefined ) { // using PtrToStringAnsi, based on Matt's comment, if it fails, try PtrToStringAuto string filename = Marshal.PtrToStringAnsi(ptrFileName); Console.WriteLine("Filename of WOW16 process: {0}", filename); return false; // false continues enumeration } }