/ src / modules / MouseWithoutBorders / App / Class / Setting.cs
Setting.cs
   1  // Copyright (c) Microsoft Corporation
   2  // The Microsoft Corporation licenses this file to you under the MIT license.
   3  // See the LICENSE file in the project root for more information.
   4  
   5  using System;
   6  using System.Collections;
   7  using System.Collections.Generic;
   8  using System.Diagnostics;
   9  using System.Diagnostics.CodeAnalysis;
  10  using System.Globalization;
  11  using System.IO;
  12  using System.IO.Abstractions;
  13  using System.Linq;
  14  using System.Security.Cryptography;
  15  using System.Text.Json.Serialization;
  16  using System.Threading.Tasks;
  17  using System.Windows.Forms;
  18  
  19  using global::PowerToys.GPOWrapper;
  20  using Microsoft.PowerToys.Settings.UI.Library;
  21  using Microsoft.PowerToys.Settings.UI.Library.Utilities;
  22  
  23  // <summary>
  24  //     Application settings.
  25  // </summary>
  26  // <history>
  27  //     2008 created by Truong Do (ductdo).
  28  //     2009-... modified by Truong Do (TruongDo).
  29  //     2023- Included in PowerToys.
  30  // </history>
  31  using Microsoft.Win32;
  32  using MouseWithoutBorders.Core;
  33  using Settings.UI.Library.Attributes;
  34  
  35  using Lock = System.Threading.Lock;
  36  using SettingsHelper = Microsoft.PowerToys.Settings.UI.Library.Utilities.Helper;
  37  
  38  [module: SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes", Scope = "member", Target = "MouseWithoutBorders.Properties.Setting.Values.#LoadIntSetting(System.String,System.Int32)", Justification = "Dotnet port with style preservation")]
  39  [module: SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes", Scope = "member", Target = "MouseWithoutBorders.Properties.Setting.Values.#SaveSetting(System.String,System.Object)", Justification = "Dotnet port with style preservation")]
  40  [module: SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes", Scope = "member", Target = "MouseWithoutBorders.Properties.Setting.Values.#LoadStringSetting(System.String,System.String)", Justification = "Dotnet port with style preservation")]
  41  [module: SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes", Scope = "member", Target = "MouseWithoutBorders.Properties.Setting.Values.#SaveSettingQWord(System.String,System.Int64)", Justification = "Dotnet port with style preservation")]
  42  
  43  namespace MouseWithoutBorders.Class
  44  {
  45      internal class Settings
  46      {
  47          internal bool Changed;
  48  
  49          private readonly SettingsUtils _settingsUtils;
  50          private readonly Lock _loadingSettingsLock = new Lock();
  51          private readonly IFileSystemWatcher _watcher;
  52  
  53          private MouseWithoutBordersProperties _properties;
  54          private MouseWithoutBordersSettings _settings;
  55  
  56          // Avoid instantly saving every change to the file when updating properties.
  57          public bool PauseInstantSaving { get; set; }
  58  
  59          private void UpdateSettingsFromJson()
  60          {
  61              try
  62              {
  63                  if (!_settingsUtils.SettingsExists("MouseWithoutBorders"))
  64                  {
  65                      var defaultSettings = new MouseWithoutBordersSettings();
  66                      if (!Common.RunOnLogonDesktop)
  67                      {
  68                          defaultSettings.Save(_settingsUtils);
  69                      }
  70                  }
  71  
  72                  var settings = _settingsUtils.GetSettingsOrDefault<MouseWithoutBordersSettings>("MouseWithoutBorders");
  73                  if (settings != null)
  74                  {
  75                      PauseInstantSaving = true;
  76  
  77                      var last_properties = _properties;
  78  
  79                      _settings = settings;
  80  
  81                      _properties = settings.Properties;
  82  
  83                      // Keep track of the need to resend the machine matrix.
  84                      bool shouldSendMachineMatrix = false;
  85  
  86                      // Keep track of the need to save into the settings file.
  87                      bool shouldSaveNewSettingsValues = false;
  88  
  89                      if (last_properties != null)
  90                      {
  91                          // Same as in CheckBoxCircle_CheckedChanged
  92                          if (last_properties.WrapMouse != _settings.Properties.WrapMouse)
  93                          {
  94                              shouldSendMachineMatrix = true;
  95                          }
  96  
  97                          // Same as CheckBoxDrawMouse_CheckedChanged
  98                          if (last_properties.DrawMouseCursor != _settings.Properties.DrawMouseCursor && !_settings.Properties.DrawMouseCursor)
  99                          {
 100                              CustomCursor.ShowFakeMouseCursor(int.MinValue, int.MinValue);
 101                          }
 102  
 103                          if (!Enumerable.SequenceEqual(last_properties.MachineMatrixString, _settings.Properties.MachineMatrixString))
 104                          {
 105                              _properties.MachineMatrixString = _settings.Properties.MachineMatrixString;
 106                              MachineStuff.MachineMatrix = null; // Forces read next time it's needed.
 107                              shouldSendMachineMatrix = true;
 108                          }
 109  
 110                          var shouldReopenSockets = false;
 111  
 112                          if (Encryption.MyKey != _properties.SecurityKey.Value)
 113                          {
 114                              Encryption.MyKey = _properties.SecurityKey.Value;
 115                              shouldReopenSockets = true;
 116                          }
 117  
 118                          if (shouldReopenSockets)
 119                          {
 120                              SocketStuff.InvalidKeyFound = false;
 121                              InitAndCleanup.ReopenSocketDueToReadError = true;
 122                              Common.ReopenSockets(true);
 123                          }
 124  
 125                          if (shouldSendMachineMatrix)
 126                          {
 127                              MachineStuff.SendMachineMatrix();
 128                              shouldSaveNewSettingsValues = true;
 129                          }
 130  
 131                          if (shouldSaveNewSettingsValues)
 132                          {
 133                              SaveSettings();
 134                          }
 135                      }
 136                  }
 137              }
 138              catch (IOException ex)
 139              {
 140                  EventLogger.LogEvent($"Failed to read settings: {ex.Message}", System.Diagnostics.EventLogEntryType.Error);
 141              }
 142  
 143              PauseInstantSaving = false;
 144          }
 145  
 146          public void SaveSettings()
 147          {
 148              if (!Common.RunOnLogonDesktop)
 149              {
 150                  SaveSettingsToJson((MouseWithoutBordersProperties)_properties.Clone());
 151              }
 152          }
 153  
 154          private void SaveSettingsToJson(MouseWithoutBordersProperties properties_to_save)
 155          {
 156              _settings.Properties = properties_to_save;
 157              _ = Task.Factory.StartNew(
 158                  () =>
 159              {
 160                  bool saved = false;
 161  
 162                  for (int i = 0; i < 5; ++i)
 163                  {
 164                      try
 165                      {
 166                          lock (_loadingSettingsLock)
 167                          {
 168                              _settings.Save(_settingsUtils);
 169                          }
 170  
 171                          saved = true;
 172                      }
 173                      catch (IOException ex)
 174                      {
 175                          EventLogger.LogEvent($"Failed to write settings: {ex.Message}", System.Diagnostics.EventLogEntryType.Error);
 176                      }
 177  
 178                      if (saved)
 179                      {
 180                          break;
 181                      }
 182                      else
 183                      {
 184                          Thread.Sleep(500);
 185                      }
 186                  }
 187              },
 188                  System.Threading.CancellationToken.None,
 189                  TaskCreationOptions.None,
 190                  TaskScheduler.Default);
 191          }
 192  
 193          internal Settings()
 194          {
 195              _settingsUtils = SettingsUtils.Default;
 196  
 197              _watcher = SettingsHelper.GetFileWatcher("MouseWithoutBorders", "settings.json", () =>
 198              {
 199                  try
 200                  {
 201                      UpdateSettingsFromJson();
 202                  }
 203                  catch (Exception ex)
 204                  {
 205                      EventLogger.LogEvent($"Failed to update settings: {ex.Message}", System.Diagnostics.EventLogEntryType.Error);
 206                  }
 207              });
 208  
 209              UpdateSettingsFromJson();
 210          }
 211  
 212          internal string Username { get; set; }
 213  
 214          internal bool IsMyKeyRandom { get; set; }
 215  
 216          internal string MachineMatrixString
 217          {
 218              get
 219              {
 220                  lock (_loadingSettingsLock)
 221                  {
 222                      return string.Join(",", _properties.MachineMatrixString);
 223                  }
 224              }
 225  
 226              set
 227              {
 228                  lock (_loadingSettingsLock)
 229                  {
 230                      _properties.MachineMatrixString = new List<string>(value.Split(","));
 231                      if (!PauseInstantSaving)
 232                      {
 233                          SaveSettings();
 234                      }
 235                  }
 236              }
 237          }
 238  
 239          internal string MachinePoolString
 240          {
 241              get
 242              {
 243                  lock (_loadingSettingsLock)
 244                  {
 245                      return _properties.MachinePool.Value;
 246                  }
 247              }
 248  
 249              set
 250              {
 251                  lock (_loadingSettingsLock)
 252                  {
 253                      if (!value.Equals(_properties.MachinePool.Value, StringComparison.OrdinalIgnoreCase))
 254                      {
 255                          _properties.MachinePool.Value = value;
 256                      }
 257                  }
 258              }
 259          }
 260  
 261          internal string MyID => Application.ProductName + " Application";
 262  
 263          internal string MyIdEx => Application.ProductName + " Application-Ex";
 264  
 265          internal bool ShareClipboard
 266          {
 267              get
 268              {
 269                  if (GPOWrapper.GetConfiguredMwbClipboardSharingEnabledValue() == GpoRuleConfigured.Disabled)
 270                  {
 271                      return false;
 272                  }
 273  
 274                  lock (_loadingSettingsLock)
 275                  {
 276                      return _properties.ShareClipboard;
 277                  }
 278              }
 279  
 280              set
 281              {
 282                  if (ShareClipboardIsGpoConfigured)
 283                  {
 284                      return;
 285                  }
 286  
 287                  lock (_loadingSettingsLock)
 288                  {
 289                      _properties.ShareClipboard = value;
 290                  }
 291              }
 292          }
 293  
 294          [CmdConfigureIgnore]
 295          [JsonIgnore]
 296          internal bool ShareClipboardIsGpoConfigured => GPOWrapper.GetConfiguredMwbClipboardSharingEnabledValue() == GpoRuleConfigured.Disabled;
 297  
 298          internal bool TransferFile
 299          {
 300              get
 301              {
 302                  if (GPOWrapper.GetConfiguredMwbFileTransferEnabledValue() == GpoRuleConfigured.Disabled)
 303                  {
 304                      return false;
 305                  }
 306  
 307                  lock (_loadingSettingsLock)
 308                  {
 309                      return _properties.TransferFile;
 310                  }
 311              }
 312  
 313              set
 314              {
 315                  if (TransferFileIsGpoConfigured)
 316                  {
 317                      return;
 318                  }
 319  
 320                  _properties.TransferFile = value;
 321              }
 322          }
 323  
 324          [CmdConfigureIgnore]
 325          [JsonIgnore]
 326          internal bool TransferFileIsGpoConfigured => GPOWrapper.GetConfiguredMwbFileTransferEnabledValue() == GpoRuleConfigured.Disabled;
 327  
 328          internal bool MatrixOneRow
 329          {
 330              get
 331              {
 332                  lock (_loadingSettingsLock)
 333                  {
 334                      return _properties.MatrixOneRow;
 335                  }
 336              }
 337  
 338              set
 339              {
 340                  lock (_loadingSettingsLock)
 341                  {
 342                      _properties.MatrixOneRow = value;
 343                      if (!PauseInstantSaving)
 344                      {
 345                          SaveSettings();
 346                      }
 347                  }
 348              }
 349          }
 350  
 351          internal bool MatrixCircle
 352          {
 353              get
 354              {
 355                  lock (_loadingSettingsLock)
 356                  {
 357                      return _properties.WrapMouse;
 358                  }
 359              }
 360  
 361              set
 362              {
 363                  lock (_loadingSettingsLock)
 364                  {
 365                      _properties.WrapMouse = value;
 366                      if (!PauseInstantSaving)
 367                      {
 368                          SaveSettings();
 369                      }
 370                  }
 371              }
 372          }
 373  
 374          internal int EasyMouse
 375          {
 376              get
 377              {
 378                  lock (_loadingSettingsLock)
 379                  {
 380                      return _properties.EasyMouse.Value;
 381                  }
 382              }
 383  
 384              set
 385              {
 386                  lock (_loadingSettingsLock)
 387                  {
 388                      _properties.EasyMouse.Value = value;
 389                      if (!PauseInstantSaving)
 390                      {
 391                          // Easy Mouse can be enabled or disabled through a shortcut, so a save is required.
 392                          SaveSettings();
 393                      }
 394                  }
 395              }
 396          }
 397  
 398          internal bool BlockMouseAtCorners
 399          {
 400              get
 401              {
 402                  lock (_loadingSettingsLock)
 403                  {
 404                      return _properties.BlockMouseAtScreenCorners;
 405                  }
 406              }
 407  
 408              set
 409              {
 410                  lock (_loadingSettingsLock)
 411                  {
 412                      _properties.BlockMouseAtScreenCorners = value;
 413                  }
 414              }
 415          }
 416  
 417          internal bool DisableEasyMouseWhenForegroundWindowIsFullscreen
 418          {
 419              get
 420              {
 421                  lock (_loadingSettingsLock)
 422                  {
 423                      return _properties.DisableEasyMouseWhenForegroundWindowIsFullscreen;
 424                  }
 425              }
 426  
 427              set
 428              {
 429                  lock (_loadingSettingsLock)
 430                  {
 431                      _properties.DisableEasyMouseWhenForegroundWindowIsFullscreen = value;
 432                  }
 433              }
 434          }
 435  
 436          internal HashSet<string> EasyMouseFullscreenSwitchBlockExcludedApps
 437          {
 438              get
 439              {
 440                  lock (_loadingSettingsLock)
 441                  {
 442                      return _properties.EasyMouseFullscreenSwitchBlockExcludedApps.Value;
 443                  }
 444              }
 445  
 446              set
 447              {
 448                  lock (_loadingSettingsLock)
 449                  {
 450                      _properties.EasyMouseFullscreenSwitchBlockExcludedApps.Value = value;
 451                  }
 452              }
 453          }
 454  
 455          internal string Enc(string st, bool dec, DataProtectionScope protectionScope)
 456          {
 457              if (st == null || st.Length < 1)
 458              {
 459                  return string.Empty;
 460              }
 461  
 462              byte[] ep = Common.GetBytesU(st);
 463              byte[] rv, st2;
 464  
 465              if (dec)
 466              {
 467                  st2 = Convert.FromBase64String(st);
 468                  rv = ProtectedData.Unprotect(st2, ep, protectionScope);
 469                  return Common.GetStringU(rv);
 470              }
 471              else
 472              {
 473                  st2 = Common.GetBytesU(st);
 474                  rv = ProtectedData.Protect(st2, ep, protectionScope);
 475                  return Convert.ToBase64String(rv);
 476              }
 477          }
 478  
 479          internal string MyKey
 480          {
 481              get
 482              {
 483                  lock (_loadingSettingsLock)
 484                  {
 485                      if (_properties.SecurityKey.Value.Length != 0)
 486                      {
 487                          Logger.LogDebug("GETSECKEY: Key was already loaded/set: " + _properties.SecurityKey.Value);
 488                          return _properties.SecurityKey.Value;
 489                      }
 490                      else
 491                      {
 492                          string randomKey = Encryption.CreateDefaultKey();
 493                          _properties.SecurityKey.Value = randomKey;
 494  
 495                          return randomKey;
 496                      }
 497                  }
 498              }
 499  
 500              set
 501              {
 502                  lock (_loadingSettingsLock)
 503                  {
 504                      _properties.SecurityKey.Value = value;
 505                      if (!PauseInstantSaving)
 506                      {
 507                          SaveSettings();
 508                      }
 509                  }
 510              }
 511          }
 512  
 513          internal int MyKeyDaysToExpire
 514          {
 515              get
 516              {
 517                  lock (_loadingSettingsLock)
 518                  {
 519                      return int.MaxValue; // TODO(@yuyoyuppe): do we still need expiration mechanics now?
 520                  }
 521              }
 522          }
 523  
 524          // Note(@htcfreek): Settings UI CheckBox is disabled in frmMatrix.cs > FrmMatrix_Load()
 525          // Note(@htcfreek): If this settings gets implemented in the future we need a Group Policy for it!
 526          internal bool DisableCAD
 527          {
 528              get
 529              {
 530                  return false;
 531              }
 532          }
 533  
 534          // Note(@htcfreek): Settings UI CheckBox is disabled in frmMatrix.cs > FrmMatrix_Load()
 535          // Note(@htcfreek): If this settings gets implemented in the future we need a Group Policy for it!
 536          internal bool HideLogonLogo
 537          {
 538              get
 539              {
 540                  return false;
 541              }
 542          }
 543  
 544          internal bool HideMouse
 545          {
 546              get
 547              {
 548                  lock (_loadingSettingsLock)
 549                  {
 550                      return _properties.HideMouseAtScreenEdge;
 551                  }
 552              }
 553  
 554              set
 555              {
 556                  lock (_loadingSettingsLock)
 557                  {
 558                      _properties.HideMouseAtScreenEdge = value;
 559                  }
 560              }
 561          }
 562  
 563          internal bool BlockScreenSaver
 564          {
 565              get
 566              {
 567                  if (GPOWrapper.GetConfiguredMwbDisallowBlockingScreensaverValue() == GpoRuleConfigured.Enabled)
 568                  {
 569                      return false;
 570                  }
 571  
 572                  lock (_loadingSettingsLock)
 573                  {
 574                      return _properties.BlockScreenSaverOnOtherMachines;
 575                  }
 576              }
 577  
 578              set
 579              {
 580                  if (BlockScreenSaverIsGpoConfigured)
 581                  {
 582                      return;
 583                  }
 584  
 585                  lock (_loadingSettingsLock)
 586                  {
 587                      _properties.BlockScreenSaverOnOtherMachines = value;
 588                  }
 589              }
 590          }
 591  
 592          [CmdConfigureIgnore]
 593          [JsonIgnore]
 594          internal bool BlockScreenSaverIsGpoConfigured => GPOWrapper.GetConfiguredMwbDisallowBlockingScreensaverValue() == GpoRuleConfigured.Enabled;
 595  
 596          internal bool MoveMouseRelatively
 597          {
 598              get
 599              {
 600                  lock (_loadingSettingsLock)
 601                  {
 602                      return _properties.MoveMouseRelatively;
 603                  }
 604              }
 605  
 606              set
 607              {
 608                  lock (_loadingSettingsLock)
 609                  {
 610                      _properties.MoveMouseRelatively = value;
 611                  }
 612              }
 613          }
 614  
 615          internal string LastPersonalizeLogonScr
 616          {
 617              get
 618              {
 619                  return string.Empty;
 620              }
 621          }
 622  
 623          internal uint DesMachineID
 624          {
 625              get
 626              {
 627                  lock (_loadingSettingsLock)
 628                  {
 629                      return (uint)_properties.MachineID.Value;
 630                  }
 631              }
 632  
 633              set
 634              {
 635                  lock (_loadingSettingsLock)
 636                  {
 637                      _properties.MachineID.Value = (int)value;
 638                  }
 639              }
 640          }
 641  
 642          internal int LastX
 643          {
 644              get
 645              {
 646                  lock (_loadingSettingsLock)
 647                  {
 648                      return _properties.LastX.Value;
 649                  }
 650              }
 651  
 652              set
 653              {
 654                  lock (_loadingSettingsLock)
 655                  {
 656                      Common.LastX = value;
 657                      _properties.LastX.Value = value;
 658                  }
 659              }
 660          }
 661  
 662          internal int LastY
 663          {
 664              get
 665              {
 666                  lock (_loadingSettingsLock)
 667                  {
 668                      return _properties.LastY.Value;
 669                  }
 670              }
 671  
 672              set
 673              {
 674                  lock (_loadingSettingsLock)
 675                  {
 676                      Common.LastY = value;
 677                      _properties.LastY.Value = value;
 678                  }
 679              }
 680          }
 681  
 682          internal int PackageID
 683          {
 684              get
 685              {
 686                  lock (_loadingSettingsLock)
 687                  {
 688                      return _properties.PackageID.Value;
 689                  }
 690              }
 691  
 692              set
 693              {
 694                  lock (_loadingSettingsLock)
 695                  {
 696                      _properties.PackageID.Value = value;
 697                  }
 698              }
 699          }
 700  
 701          internal bool FirstRun
 702          {
 703              get
 704              {
 705                  lock (_loadingSettingsLock)
 706                  {
 707                      return _properties.FirstRun;
 708                  }
 709              }
 710  
 711              set
 712              {
 713                  lock (_loadingSettingsLock)
 714                  {
 715                      _properties.FirstRun = value;
 716                      if (!PauseInstantSaving)
 717                      {
 718                          SaveSettings();
 719                      }
 720                  }
 721              }
 722          }
 723  
 724          internal int HotKeySwitchMachine
 725          {
 726              get
 727              {
 728                  lock (_loadingSettingsLock)
 729                  {
 730                      return _properties.HotKeySwitchMachine.Value;
 731                  }
 732              }
 733  
 734              set
 735              {
 736                  lock (_loadingSettingsLock)
 737                  {
 738                      _properties.HotKeySwitchMachine.Value = value;
 739                  }
 740              }
 741          }
 742  
 743          internal HotkeySettings HotKeySwitch2AllPC
 744          {
 745              get
 746              {
 747                  lock (_loadingSettingsLock)
 748                  {
 749                      return _properties.Switch2AllPCShortcut;
 750                  }
 751              }
 752          }
 753  
 754          internal HotkeySettings HotKeyToggleEasyMouse
 755          {
 756              get
 757              {
 758                  lock (_loadingSettingsLock)
 759                  {
 760                      return _properties.ToggleEasyMouseShortcut;
 761                  }
 762              }
 763  
 764              set
 765              {
 766                  lock (_loadingSettingsLock)
 767                  {
 768                      _properties.ToggleEasyMouseShortcut = value;
 769                  }
 770              }
 771          }
 772  
 773          internal HotkeySettings HotKeyLockMachine
 774          {
 775              get
 776              {
 777                  lock (_loadingSettingsLock)
 778                  {
 779                      return _properties.LockMachineShortcut;
 780                  }
 781              }
 782  
 783              set
 784              {
 785                  lock (_loadingSettingsLock)
 786                  {
 787                      _properties.LockMachineShortcut = value;
 788                  }
 789              }
 790          }
 791  
 792          internal HotkeySettings HotKeyReconnect
 793          {
 794              get
 795              {
 796                  lock (_loadingSettingsLock)
 797                  {
 798                      return _properties.ReconnectShortcut;
 799                  }
 800              }
 801  
 802              set
 803              {
 804                  lock (_loadingSettingsLock)
 805                  {
 806                      _properties.ReconnectShortcut = value;
 807                  }
 808              }
 809          }
 810  
 811          internal int HotKeyExitMM
 812          {
 813              get
 814              {
 815                  return 0;
 816              }
 817          }
 818  
 819          private int switchCount;
 820  
 821          internal int SwitchCount
 822          {
 823              get
 824              {
 825                  return switchCount;
 826              }
 827  
 828              set
 829              {
 830                  switchCount = value;
 831                  if (!PauseInstantSaving)
 832                  {
 833                      SaveSettings();
 834                  }
 835              }
 836          }
 837  
 838          internal int DumpObjectsLevel => 6;
 839  
 840          internal int TcpPort => _properties.TCPPort.Value;
 841  
 842          internal bool DrawMouse
 843          {
 844              get
 845              {
 846                  lock (_loadingSettingsLock)
 847                  {
 848                      return _properties.DrawMouseCursor;
 849                  }
 850              }
 851  
 852              set
 853              {
 854                  lock (_loadingSettingsLock)
 855                  {
 856                      _properties.DrawMouseCursor = value;
 857                  }
 858              }
 859          }
 860  
 861          [CmdConfigureIgnore]
 862          internal bool DrawMouseEx
 863          {
 864              get
 865              {
 866                  lock (_loadingSettingsLock)
 867                  {
 868                      return _properties.DrawMouseEx;
 869                  }
 870              }
 871  
 872              set
 873              {
 874                  lock (_loadingSettingsLock)
 875                  {
 876                      _properties.DrawMouseEx = value;
 877                  }
 878              }
 879          }
 880  
 881          internal bool ReverseLookup
 882          {
 883              get
 884              {
 885                  if (GPOWrapper.GetConfiguredMwbValidateRemoteIpValue() == GpoRuleConfigured.Enabled)
 886                  {
 887                      return true;
 888                  }
 889                  else if (GPOWrapper.GetConfiguredMwbValidateRemoteIpValue() == GpoRuleConfigured.Disabled)
 890                  {
 891                      return false;
 892                  }
 893  
 894                  lock (_loadingSettingsLock)
 895                  {
 896                      return _properties.ValidateRemoteMachineIP;
 897                  }
 898              }
 899  
 900              set
 901              {
 902                  if (ReverseLookupIsGpoConfigured)
 903                  {
 904                      return;
 905                  }
 906  
 907                  lock (_loadingSettingsLock)
 908                  {
 909                      _properties.ValidateRemoteMachineIP = value;
 910                  }
 911              }
 912          }
 913  
 914          [CmdConfigureIgnore]
 915          [JsonIgnore]
 916          internal bool ReverseLookupIsGpoConfigured => GPOWrapper.GetConfiguredMwbValidateRemoteIpValue() == GpoRuleConfigured.Enabled || GPOWrapper.GetConfiguredMwbValidateRemoteIpValue() == GpoRuleConfigured.Disabled;
 917  
 918          internal bool SameSubNetOnly
 919          {
 920              get
 921              {
 922                  if (GPOWrapper.GetConfiguredMwbSameSubnetOnlyValue() == GpoRuleConfigured.Enabled)
 923                  {
 924                      return true;
 925                  }
 926                  else if (GPOWrapper.GetConfiguredMwbSameSubnetOnlyValue() == GpoRuleConfigured.Disabled)
 927                  {
 928                      return false;
 929                  }
 930  
 931                  lock (_loadingSettingsLock)
 932                  {
 933                      return _properties.SameSubnetOnly;
 934                  }
 935              }
 936  
 937              set
 938              {
 939                  if (SameSubNetOnlyIsGpoConfigured)
 940                  {
 941                      return;
 942                  }
 943  
 944                  lock (_loadingSettingsLock)
 945                  {
 946                      _properties.SameSubnetOnly = value;
 947                  }
 948              }
 949          }
 950  
 951          [CmdConfigureIgnore]
 952          [JsonIgnore]
 953          internal bool SameSubNetOnlyIsGpoConfigured => GPOWrapper.GetConfiguredMwbSameSubnetOnlyValue() == GpoRuleConfigured.Enabled || GPOWrapper.GetConfiguredMwbSameSubnetOnlyValue() == GpoRuleConfigured.Disabled;
 954  
 955          internal string Name2IP
 956          {
 957              get
 958              {
 959                  if (GPOWrapper.GetConfiguredMwbDisableUserDefinedIpMappingRulesValue() == GpoRuleConfigured.Enabled)
 960                  {
 961                      return string.Empty;
 962                  }
 963  
 964                  lock (_loadingSettingsLock)
 965                  {
 966                      return _properties.Name2IP.Value;
 967                  }
 968              }
 969  
 970              set
 971              {
 972                  if (Name2IpIsGpoConfigured)
 973                  {
 974                      return;
 975                  }
 976  
 977                  lock (_loadingSettingsLock)
 978                  {
 979                      _properties.Name2IP.Value = value;
 980                  }
 981              }
 982          }
 983  
 984          [CmdConfigureIgnore]
 985          [JsonIgnore]
 986          internal bool Name2IpIsGpoConfigured => GPOWrapper.GetConfiguredMwbDisableUserDefinedIpMappingRulesValue() == GpoRuleConfigured.Enabled;
 987  
 988          [CmdConfigureIgnore]
 989          [JsonIgnore]
 990          internal string Name2IpPolicyList => GPOWrapper.GetConfiguredMwbPolicyDefinedIpMappingRules();
 991  
 992          [CmdConfigureIgnore]
 993          [JsonIgnore]
 994          internal bool Name2IpPolicyListIsGpoConfigured => !string.IsNullOrWhiteSpace(Name2IpPolicyList);
 995  
 996          internal bool FirstCtrlShiftS
 997          {
 998              get
 999              {
1000                  lock (_loadingSettingsLock)
1001                  {
1002                      return _properties.FirstCtrlShiftS;
1003                  }
1004              }
1005  
1006              set
1007              {
1008                  lock (_loadingSettingsLock)
1009                  {
1010                      _properties.FirstCtrlShiftS = value;
1011                  }
1012              }
1013          }
1014  
1015          // Was a value read from registry on original Mouse Without Border, but default should be true. We wrongly released it as false, so we're forcing true here.
1016          // This value wasn't changeable from UI, anyway.
1017          internal bool StealFocusWhenSwitchingMachine => true;
1018  
1019          private string deviceId;
1020  
1021          internal string DeviceId
1022          {
1023              get
1024              {
1025                  string newGuid = Guid.NewGuid().ToString();
1026  
1027                  if (deviceId == null || deviceId.Length != newGuid.Length)
1028                  {
1029                      string defaultId = newGuid;
1030                      lock (_loadingSettingsLock)
1031                      {
1032                          _properties.DeviceID = defaultId;
1033                          deviceId = _properties.DeviceID.Value;
1034  
1035                          if (deviceId.Equals(defaultId, StringComparison.OrdinalIgnoreCase))
1036                          {
1037                              return _properties.DeviceID.Value;
1038                          }
1039                      }
1040                  }
1041  
1042                  return deviceId;
1043              }
1044          }
1045  
1046          private int? machineId;
1047  
1048          internal int MachineId
1049          {
1050              get
1051              {
1052                  lock (_loadingSettingsLock)
1053                  {
1054                      machineId ??= (machineId = _properties.MachineID.Value).Value;
1055  
1056                      if (machineId == 0)
1057                      {
1058                          var newMachineId = Encryption.Ran.Next();
1059                          _properties.MachineID.Value = newMachineId;
1060                          machineId = newMachineId;
1061                          if (!PauseInstantSaving)
1062                          {
1063                              SaveSettings();
1064                          }
1065                      }
1066                  }
1067  
1068                  return machineId.Value;
1069              }
1070  
1071              set
1072              {
1073                  lock (_loadingSettingsLock)
1074                  {
1075                      _properties.MachineID.Value = value;
1076                      machineId = value;
1077                      if (!PauseInstantSaving)
1078                      {
1079                          SaveSettings();
1080                      }
1081                  }
1082              }
1083          }
1084  
1085          internal bool OneWayControlMode => false;
1086  
1087          internal bool OneWayClipboardMode => false;
1088  
1089          internal bool ShowClipNetStatus
1090          {
1091              get
1092              {
1093                  lock (_loadingSettingsLock)
1094                  {
1095                      return _properties.ShowClipboardAndNetworkStatusMessages;
1096                  }
1097              }
1098  
1099              set
1100              {
1101                  lock (_loadingSettingsLock)
1102                  {
1103                      _properties.ShowClipboardAndNetworkStatusMessages = value;
1104                  }
1105              }
1106          }
1107  
1108          internal bool ShowOriginalUI
1109          {
1110              get
1111              {
1112                  if (GPOWrapper.GetConfiguredMwbUseOriginalUserInterfaceValue() == GpoRuleConfigured.Disabled)
1113                  {
1114                      return false;
1115                  }
1116  
1117                  lock (_loadingSettingsLock)
1118                  {
1119                      return _properties.ShowOriginalUI;
1120                  }
1121              }
1122  
1123              set
1124              {
1125                  if (GPOWrapper.GetConfiguredMwbUseOriginalUserInterfaceValue() == GpoRuleConfigured.Disabled)
1126                  {
1127                      return;
1128                  }
1129  
1130                  lock (_loadingSettingsLock)
1131                  {
1132                      _properties.ShowOriginalUI = value;
1133                  }
1134              }
1135          }
1136  
1137          // If starting the service fails, work in not service mode.
1138          internal bool UseService
1139          {
1140              get
1141              {
1142                  if (GPOWrapper.GetConfiguredMwbAllowServiceModeValue() == GpoRuleConfigured.Disabled)
1143                  {
1144                      return false;
1145                  }
1146  
1147                  lock (_loadingSettingsLock)
1148                  {
1149                      return _properties.UseService;
1150                  }
1151              }
1152  
1153              set
1154              {
1155                  if (AllowServiceModeIsGpoConfigured)
1156                  {
1157                      return;
1158                  }
1159  
1160                  lock (_loadingSettingsLock)
1161                  {
1162                      _properties.UseService = value;
1163                      if (!PauseInstantSaving)
1164                      {
1165                          SaveSettings();
1166                      }
1167                  }
1168              }
1169          }
1170  
1171          [CmdConfigureIgnore]
1172          [JsonIgnore]
1173          internal bool AllowServiceModeIsGpoConfigured => GPOWrapper.GetConfiguredMwbAllowServiceModeValue() == GpoRuleConfigured.Disabled;
1174  
1175          // Note(@htcfreek): Settings UI CheckBox is disabled in frmMatrix.cs > FrmMatrix_Load()
1176          internal bool SendErrorLogV2
1177          {
1178              get
1179              {
1180                  return false;
1181              }
1182          }
1183      }
1184  
1185      public static class Setting
1186      {
1187          internal static Settings Values = new Settings();
1188      }
1189  }