private void SafeInvokeRecordingStarted(CaptureConfig config)
        {
            if (RecordingStarted == null)
            {
                return;         //No Listeners
            }
            RecordingStartedEvent listener = null;

            Delegate[] dels = RecordingStarted.GetInvocationList();

            foreach (Delegate del in dels)
            {
                try
                {
                    listener = (RecordingStartedEvent)del;
                    listener.Invoke(config);
                }
                catch (Exception)
                {
                    //Could not reach the destination, so remove it
                    //from the list
                    RecordingStarted -= listener;
                }
            }
        }
 public void RecordingStartedProxyHandler(CaptureConfig config)
 {
     if (RecordingStarted != null)
     {
         RecordingStarted(config);
     }
 }
Example #3
0
        public EntryPoint(
            EasyHook.RemoteHooking.IContext context,
            String channelName,
            CaptureConfig config)
        {
            // Get reference to IPC to host application
            // Note: any methods called or events triggered against _interface will execute in the host process.
            _interface = EasyHook.RemoteHooking.IpcConnectClient<CaptureInterface>(channelName);

            // We try to ping immediately, if it fails then injection fails
            _interface.Ping();

            #region Allow client event handlers (bi-directional IPC)
            
            // Attempt to create a IpcServerChannel so that any event handlers on the client will function correctly
            System.Collections.IDictionary properties = new System.Collections.Hashtable();
            properties["name"] = channelName;
            properties["portName"] = channelName + Guid.NewGuid().ToString("N"); // random portName so no conflict with existing channels of channelName

            System.Runtime.Remoting.Channels.BinaryServerFormatterSinkProvider binaryProv = new System.Runtime.Remoting.Channels.BinaryServerFormatterSinkProvider();
            binaryProv.TypeFilterLevel = System.Runtime.Serialization.Formatters.TypeFilterLevel.Full;

            System.Runtime.Remoting.Channels.Ipc.IpcServerChannel _clientServerChannel = new System.Runtime.Remoting.Channels.Ipc.IpcServerChannel(properties, binaryProv);
            System.Runtime.Remoting.Channels.ChannelServices.RegisterChannel(_clientServerChannel, false);
            
            #endregion
        }
 /// <summary>
 /// If not <see cref="IsRecording"/> will invoke the <see cref="RecordingStarted"/> event, starting a new recording.
 /// </summary>
 /// <param name="config">The configuration for the recording</param>
 /// <remarks>Handlers in the server and remote process will be be invoked.</remarks>
 public void StartRecording(CaptureConfig config)
 {
     if (IsRecording)
     {
         return;
     }
     SafeInvokeRecordingStarted(config);
     IsRecording = true;
 }
        /// <summary>
        /// Prepares capturing in the target process. Note that the process must not already be hooked, and must have a <see cref="Process.MainWindowHandle"/>.
        /// </summary>
        /// <param name="process">The process to inject into</param>
        /// <exception cref="ProcessHasNoWindowHandleException">Thrown if the <paramref name="process"/> does not have a window handle. This could mean that the process does not have a UI, or that the process has not yet finished starting.</exception>
        /// <exception cref="ProcessAlreadyHookedException">Thrown if the <paramref name="process"/> is already hooked</exception>
        /// <exception cref="InjectionFailedException">Thrown if the injection failed - see the InnerException for more details.</exception>
        /// <remarks>The target process will have its main window brought to the foreground after successful injection.</remarks>
        public CaptureProcess(Process process, CaptureConfig config, CaptureInterface captureInterface)
        {
            // If the process doesn't have a mainwindowhandle yet, skip it (we need to be able to get the hwnd to set foreground etc)
            //if (process.MainWindowHandle == IntPtr.Zero)
            //{
            //    throw new ProcessHasNoWindowHandleException();
            //}

            // Skip if the process is already hooked (and we want to hook multiple applications)
            if (HookManager.IsHooked(process.Id))
            {
                throw new ProcessAlreadyHookedException();
            }

            captureInterface.ProcessId = process.Id;
            this._serverInterface = captureInterface;
            //_serverInterface = new CaptureInterface() { ProcessId = process.Id };

            // Initialise the IPC server (with our instance of _serverInterface)
            this._screenshotServer = RemoteHooking.IpcCreateServer<CaptureInterface>(
                ref this._channelName,
                WellKnownObjectMode.Singleton,
                this._serverInterface);

            try
            {
                var location = typeof(CaptureInterface).Assembly.Location;
                if (String.IsNullOrEmpty(location))
                {
                    var dllName = typeof(CaptureInterface).Assembly.GetName().Name + ".dll";
                    location = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, dllName);
                }

                // Inject DLL into target process
                RemoteHooking.Inject(
                    process.Id,
                    InjectionOptions.Default,
                    location,
                    //"Capture.dll", // 32-bit version (the same because AnyCPU) could use different assembly that links to 32-bit C++ helper dll
                    location,
                    //"Capture.dll", // 64-bit version (the same because AnyCPU) could use different assembly that links to 64-bit C++ helper dll
                    // the optional parameter list...
                    this._channelName,
                    // The name of the IPC channel for the injected assembly to connect to
                    config
                    );
            }
            catch (Exception e)
            {
                throw new InjectionFailedException(e);
            }

            HookManager.AddHookedProcess(process.Id);

            this.Process = process;
        }
Example #6
0
        /// <summary>
        /// Prepares capturing in the target process. Note that the process must not already be hooked, and must have a <see cref="Process.MainWindowHandle"/>.
        /// </summary>
        /// <param name="process">The process to inject into</param>
        /// <exception cref="ProcessHasNoWindowHandleException">Thrown if the <paramref name="process"/> does not have a window handle. This could mean that the process does not have a UI, or that the process has not yet finished starting.</exception>
        /// <exception cref="ProcessAlreadyHookedException">Thrown if the <paramref name="process"/> is already hooked</exception>
        /// <exception cref="InjectionFailedException">Thrown if the injection failed - see the InnerException for more details.</exception>
        /// <remarks>The target process will have its main window brought to the foreground after successful injection.</remarks>
        public CaptureProcess(Process process, CaptureConfig config, CaptureInterface captureInterface)
        {
            // If the process doesn't have a mainwindowhandle yet, skip it (we need to be able to get the hwnd to set foreground etc)
            if (process.MainWindowHandle == IntPtr.Zero)
            {
                throw new ProcessHasNoWindowHandleException();
            }

            // Skip if the process is already hooked (and we want to hook multiple applications)
            if (HookManager.IsHooked(process.Id))
            {
                throw new ProcessAlreadyHookedException();
            }

            captureInterface.ProcessId = process.Id;
            _serverInterface = captureInterface;
            //_serverInterface = new CaptureInterface() { ProcessId = process.Id };

            // Initialise the IPC server (with our instance of _serverInterface)
            _screenshotServer = RemoteHooking.IpcCreateServer<CaptureInterface>(
                ref _channelName,
                WellKnownObjectMode.Singleton,
                _serverInterface);

            try
            {

                // Inject DLL into target process
                RemoteHooking.Inject(
                    process.Id,
                    InjectionOptions.Default,
                    typeof(CaptureInterface).Assembly.Location,//"Capture.dll", // 32-bit version (the same because AnyCPU) could use different assembly that links to 32-bit C++ helper dll
                    typeof(CaptureInterface).Assembly.Location, //"Capture.dll", // 64-bit version (the same because AnyCPU) could use different assembly that links to 64-bit C++ helper dll
                    // the optional parameter list...
                    _channelName, // The name of the IPC channel for the injected assembly to connect to
                    config
                );
            }
            catch (Exception e)
            {
                throw new InjectionFailedException(e);
            }

            HookManager.AddHookedProcess(process.Id);

            Process = process;

            // Ensure the target process is in the foreground,
            // this prevents an issue where the target app appears to be in 
            // the foreground but does not receive any user inputs.
            // Note: the first Alt+Tab out of the target application after injection
            //       may still be an issue - switching between windowed and 
            //       fullscreen fixes the issue however (see ScreenshotInjection.cs for another option)
            BringProcessWindowToFront();
        }
Example #7
0
        public void Run(
            EasyHook.RemoteHooking.IContext context,
            String channelName,
            CaptureConfig config)
        {
            // When not using GAC there can be issues with remoting assemblies resolving correctly
            // this is a workaround that ensures that the current assembly is correctly associated
            AppDomain currentDomain = AppDomain.CurrentDomain;
            currentDomain.AssemblyResolve += (sender, args) =>
            {
                return this.GetType().Assembly.FullName == args.Name ? this.GetType().Assembly : null;
            };

            // NOTE: This is running in the target process
            _interface.Message(MessageType.Information, "Injected into process Id:{0}.", EasyHook.RemoteHooking.GetCurrentProcessId());

            _runWait = new System.Threading.ManualResetEvent(false);
            _runWait.Reset();
            try
            {
                // Initialise the Hook
                if (!InitialiseDirectXHook(config))
                {
                    return;
                }
                _interface.Disconnected += _clientEventProxy.DisconnectedProxyHandler;

                // Important Note:
                // accessing the _interface from within a _clientEventProxy event handler must always 
                // be done on a different thread otherwise it will cause a deadlock

                _clientEventProxy.Disconnected += () =>
                {
                    // We can now signal the exit of the Run method
                    _runWait.Set();
                };

                // We start a thread here to periodically check if the host is still running
                // If the host process stops then we will automatically uninstall the hooks
                StartCheckHostIsAliveThread();

                // Wait until signaled for exit either when a Disconnect message from the host 
                // or if the the check is alive has failed to Ping the host.
                _runWait.WaitOne();

                // we need to tell the check host thread to exit (if it hasn't already)
                StopCheckHostIsAliveThread();

                // Dispose of the DXHook so any installed hooks are removed correctly
                DisposeDirectXHook();
            }
            catch (Exception e)
            {
                _interface.Message(MessageType.Error, "An unexpected error occured: {0}", e.ToString());
            }
            finally
            {
                try
                {
                    _interface.Message(MessageType.Information, "Disconnecting from process {0}", EasyHook.RemoteHooking.GetCurrentProcessId());
                }
                catch
                {
                }

                // Remove the client server channel (that allows client event handlers)
                System.Runtime.Remoting.Channels.ChannelServices.UnregisterChannel(_clientServerChannel);

                // Always sleep long enough for any remaining messages to complete sending
                System.Threading.Thread.Sleep(100);
            }
        }
Example #8
0
        private bool InitialiseDirectXHook(CaptureConfig config)
        {
            Direct3DVersion version = config.Direct3DVersion;

            List<Direct3DVersion> loadedVersions = new List<Direct3DVersion>();

            bool isX64Process = EasyHook.RemoteHooking.IsX64Process(EasyHook.RemoteHooking.GetCurrentProcessId());
            _interface.Message(MessageType.Information, "Remote process is a {0}-bit process.", isX64Process ? "64" : "32");

            try
            {
                if (version == Direct3DVersion.AutoDetect)
                {
                    // Attempt to determine the correct version based on loaded module.
                    // In most cases this will work fine, however it is perfectly ok for an application to use a D3D10 device along with D3D11 devices
                    // so the version might matched might not be the one you want to use
                    IntPtr d3D9Loaded = IntPtr.Zero;
                    IntPtr d3D10Loaded = IntPtr.Zero;
                    IntPtr d3D10_1Loaded = IntPtr.Zero;
                    IntPtr d3D11Loaded = IntPtr.Zero;
                    IntPtr d3D11_1Loaded = IntPtr.Zero;

                    int delayTime = 100;
                    int retryCount = 0;
                    while (d3D9Loaded == IntPtr.Zero && d3D10Loaded == IntPtr.Zero && d3D10_1Loaded == IntPtr.Zero && d3D11Loaded == IntPtr.Zero && d3D11_1Loaded == IntPtr.Zero)
                    {
                        retryCount++;
                        d3D9Loaded = NativeMethods.GetModuleHandle("d3d9.dll");
                        d3D10Loaded = NativeMethods.GetModuleHandle("d3d10.dll");
                        d3D10_1Loaded = NativeMethods.GetModuleHandle("d3d10_1.dll");
                        d3D11Loaded = NativeMethods.GetModuleHandle("d3d11.dll");
                        d3D11_1Loaded = NativeMethods.GetModuleHandle("d3d11_1.dll");
                        System.Threading.Thread.Sleep(delayTime);

                        if (retryCount * delayTime > 5000)
                        {
                            _interface.Message(MessageType.Error, "Unsupported Direct3D version, or Direct3D DLL not loaded within 5 seconds.");
                            return false;
                        }
                    }

                    version = Direct3DVersion.Unknown;
                    if (d3D11_1Loaded != IntPtr.Zero)
                    {
                        _interface.Message(MessageType.Debug, "Autodetect found Direct3D 11.1");
                        version = Direct3DVersion.Direct3D11_1;
                        loadedVersions.Add(version);
                    }
                    if (d3D11Loaded != IntPtr.Zero)
                    {
                        _interface.Message(MessageType.Debug, "Autodetect found Direct3D 11");
                        version = Direct3DVersion.Direct3D11;
                        loadedVersions.Add(version);
                    }
                    if (d3D10_1Loaded != IntPtr.Zero)
                    {
                        _interface.Message(MessageType.Debug, "Autodetect found Direct3D 10.1");
                        version = Direct3DVersion.Direct3D10_1;
                        loadedVersions.Add(version);
                    }
                    if (d3D10Loaded != IntPtr.Zero)
                    {
                        _interface.Message(MessageType.Debug, "Autodetect found Direct3D 10");
                        version = Direct3DVersion.Direct3D10;
                        loadedVersions.Add(version);
                    }
                    if (d3D9Loaded != IntPtr.Zero)
                    {
                        _interface.Message(MessageType.Debug, "Autodetect found Direct3D 9");
                        version = Direct3DVersion.Direct3D9;
                        loadedVersions.Add(version);
                    }
                }

                foreach (var dxVersion in loadedVersions)
                {
                    version = dxVersion;
                    switch (version)
                    {
                        case Direct3DVersion.Direct3D9:
                            _directXHook = new DXHookD3D9(_interface);
                            break;
                        case Direct3DVersion.Direct3D10:
                            _directXHook = new DXHookD3D10(_interface);
                            break;
                        case Direct3DVersion.Direct3D10_1:
                            _directXHook = new DXHookD3D10_1(_interface);
                            break;
                        case Direct3DVersion.Direct3D11:
                            _directXHook = new DXHookD3D11(_interface);
                            break;
                        //case Direct3DVersion.Direct3D11_1:
                        //    _directXHook = new DXHookD3D11_1(_interface);
                        //    return;
                        default:
                            _interface.Message(MessageType.Error, "Unsupported Direct3D version: {0}", version);
                            return false;
                    }

                    _directXHook.Config = config;
                    _directXHook.Hook();

                    _directXHooks.Add(_directXHook);
                }

                return true;

            }
            catch (Exception e)
            {
                // Notify the host/server application about this error
                _interface.Message(MessageType.Error, "Error in InitialiseHook: {0}", e.ToString());
                return false;
            }
        }
Example #9
0
        private void AttachProcess()
        {
            string exeName = Path.GetFileNameWithoutExtension(textBox1.Text);

            Process[] processes = Process.GetProcessesByName(exeName);
            foreach (Process process in processes)
            {
                // Simply attach to the first one found.

                // If the process doesn't have a mainwindowhandle yet, skip it (we need to be able to get the hwnd to set foreground etc)
                if (process.MainWindowHandle == IntPtr.Zero)
                {
                    continue;
                }

                // Skip if the process is already hooked (and we want to hook multiple applications)
                if (HookManager.IsHooked(process.Id))
                {
                    continue;
                }

                Direct3DVersion direct3DVersion = Direct3DVersion.Direct3D10;

                if (rbDirect3D11.Checked)
                {
                    direct3DVersion = Direct3DVersion.Direct3D11;
                }
                else if (rbDirect3D10_1.Checked)
                {
                    direct3DVersion = Direct3DVersion.Direct3D10_1;
                }
                else if (rbDirect3D10.Checked)
                {
                    direct3DVersion = Direct3DVersion.Direct3D10;
                }
                else if (rbDirect3D9.Checked)
                {
                    direct3DVersion = Direct3DVersion.Direct3D9;
                }
                else if (rbAutodetect.Checked)
                {
                    direct3DVersion = Direct3DVersion.AutoDetect;
                }

                CaptureConfig cc = new CaptureConfig()
                {
                    Direct3DVersion = direct3DVersion,
                    ShowOverlay = cbDrawOverlay.Checked
                };

                processId = process.Id;
                _process = process;

                var captureInterface = new CaptureInterface();
                captureInterface.RemoteMessage += new MessageReceivedEvent(CaptureInterface_RemoteMessage);
                _captureProcess = new CaptureProcess(process, cc, captureInterface);

                break;
            }
            Thread.Sleep(10);

            if (_captureProcess == null)
            {
                MessageBox.Show("No executable found matching: '" + exeName + "'");
            }
            else
            {
                btnLoadTest.Enabled = true;
                btnCapture.Enabled = true;
            }
        }
        private void SafeInvokeRecordingStarted(CaptureConfig config)
        {
            if (RecordingStarted == null)
                return;         //No Listeners

            RecordingStartedEvent listener = null;
            Delegate[] dels = RecordingStarted.GetInvocationList();

            foreach (Delegate del in dels)
            {
                try
                {
                    listener = (RecordingStartedEvent)del;
                    listener.Invoke(config);
                }
                catch (Exception)
                {
                    //Could not reach the destination, so remove it
                    //from the list
                    RecordingStarted -= listener;
                }
            }
        }
 /// <summary>
 /// If not <see cref="IsRecording"/> will invoke the <see cref="RecordingStarted"/> event, starting a new recording. 
 /// </summary>
 /// <param name="config">The configuration for the recording</param>
 /// <remarks>Handlers in the server and remote process will be be invoked.</remarks>
 public void StartRecording(CaptureConfig config)
 {
     if (IsRecording)
         return;
     SafeInvokeRecordingStarted(config);
     IsRecording = true;
 }
 public void RecordingStartedProxyHandler(CaptureConfig config)
 {
     if (RecordingStarted != null)
         RecordingStarted(config);
 }
Example #13
0
        private void CreateCaptureProcess(Process process)
        {
            _process = process;

            Direct3DVersion direct3DVersion = Direct3DVersion.Direct3D10;

            if (rbDirect3D11.Checked)
            {
                direct3DVersion = Direct3DVersion.Direct3D11;
            }
            else if (rbDirect3D10_1.Checked)
            {
                direct3DVersion = Direct3DVersion.Direct3D10_1;
            }
            else if (rbDirect3D10.Checked)
            {
                direct3DVersion = Direct3DVersion.Direct3D10;
            }
            else if (rbDirect3D9.Checked)
            {
                direct3DVersion = Direct3DVersion.Direct3D9;
            }
            else if (rbAutodetect.Checked)
            {
                direct3DVersion = Direct3DVersion.AutoDetect;
            }

            var cc = new CaptureConfig
                      {
                          Direct3DVersion = direct3DVersion,
                          ShowOverlay = cbDrawOverlay.Checked,
                          TestThisShit = 300
                      };

            var captureInterface = new CaptureInterface();

            if (frm2 != null)
            {
                frm2.Close();
                frm2.Dispose();
            }

            frm2 = new form2JT(captureInterface);

            captureInterface.RemoteMessage += CaptureInterface_RemoteMessage;
            _captureProcess = new CaptureProcess(process, cc, captureInterface);
        }
 public AutoCaptureEngine(
     IEventAggregator events,
     [ImportMany] IEnumerable<IImageScanner> imageScanners)
 {
     this.events = events;
     this.imageScanners = imageScanners;
     screenCapture = new ScreenCapture();
     var direct3DVersion = Direct3DVersion.Direct3D9SharedMem;
     CaptureMethod = CaptureMethod.AutoDetect;
     captureConfig = new CaptureConfig
         {
             Direct3DVersion = direct3DVersion
         };
     var security = new MutexSecurity();
     security.AddAccessRule(new MutexAccessRule(new SecurityIdentifier(WellKnownSidType.WorldSid, null), MutexRights.Synchronize | MutexRights.Modify, AccessControlType.Allow));
     bool created;
     sharedMemMutexes = new[]
         {
             new Mutex(false, "Global\\DXHookD3D9Shared0", out created, security),
             new Mutex(false, "Global\\DXHookD3D9Shared1", out created, security)
         };
     var ewsecurity = new EventWaitHandleSecurity();
     ewsecurity.AddAccessRule(new EventWaitHandleAccessRule(new SecurityIdentifier(WellKnownSidType.WorldSid, null), EventWaitHandleRights.FullControl, AccessControlType.Allow));
     captureDxWaitHandle = new EventWaitHandle(false, EventResetMode.ManualReset, "Global\\DXHookD3D9Capture", out created, ewsecurity);
     hookReadyWaitHandle = new EventWaitHandle(false, EventResetMode.ManualReset, "Global\\DXHookD3D9CaptureReady", out created, ewsecurity);
 }
 void Interface_RecordingStarted(CaptureConfig config)
 {
     this.targetFps = config.TargetFramesPerSecond;
     isCapturing = true;
 }