aboutsummaryrefslogtreecommitdiffstats
path: root/win/vncconfig/Legacy.cxx
blob: 3280eaefefef9883be924fdf2350f5189af39eb2 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
/* Copyright (C) 2002-2005 RealVNC Ltd.  All Rights Reserved.
 * 
 * This is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 * 
 * This software is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with this software; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,
 * USA.
 */

#include <vncconfig/Legacy.h>

#include <rfb/LogWriter.h>
#include <rfb/util.h>
#include <rfb_win32/CurrentUser.h>

using namespace rfb;
using namespace win32;

static LogWriter vlog("Legacy");


void LegacyPage::LoadPrefs()
      {
        // VNC 3.3.3R3 Preferences Algorithm, as described by vncProperties.cpp
        // - Load user-specific settings, based on logged-on user name,
        //   from HKLM/Software/ORL/WinVNC3/<user>.  If they don't exist,
        //   try again with username "Default".
        // - Load system-wide settings from HKLM/Software/ORL/WinVNC3.
        // - If AllowProperties is non-zero then load the user's own
        //   settings from HKCU/Software/ORL/WinVNC3.

        // Get the name of the current user
        std::string username;
        try {
          username = UserName();
        } catch (rdr::win32_error& e) {
          if (e.err != ERROR_NOT_LOGGED_ON)
            throw;
        }

        // Open and read the WinVNC3 registry key
        allowProperties = true;
        RegKey winvnc3;
        try {
          winvnc3.openKey(HKEY_LOCAL_MACHINE, "Software\\ORL\\WinVNC3");
          int debugMode = winvnc3.getInt("DebugMode", 0);
          const char* debugTarget = nullptr;
          if (debugMode & 2) debugTarget = "file";
          if (debugMode & 4) debugTarget = "stderr";
          if (debugTarget) {
            char logSetting[32];
            sprintf(logSetting, "*:%s:%d", debugTarget, winvnc3.getInt("DebugLevel", 0));
            regKey.setString("Log", logSetting);
          }
 
          std::string authHosts = winvnc3.getString("AuthHosts", "");
          if (!authHosts.empty()) {
            std::string newHosts;

            // Reformat AuthHosts to Hosts.  Wish I'd left the format the same. :( :( :(
            try {
              // Split the AuthHosts string into patterns to match
              std::vector<std::string> patterns;
              patterns = rfb::split(authHosts.c_str(), ':');
              for (size_t i = 0; i < patterns.size(); i++) {
                if (!patterns[i].empty()) {
                  int bits = 0;
                  char pattern[1+4*4+4];
                  pattern[0] = patterns[i][0];
                  pattern[1] = 0;

                  // Split the pattern into IP address parts and process
                  std::vector<std::string> parts;
                  parts = rfb::split(&patterns[i][1], '.');
                  for (size_t j = 0; j < parts.size(); j++) {
                    if (bits)
                      strcat(pattern, ".");
                    if (parts[j].size() > 3)
                      throw std::invalid_argument("Invalid IP address part");
                    if (!parts[j].empty()) {
                      strcat(pattern, parts[j].c_str());
                      bits += 8;
                    }
                  }

                  // Pad out the address specification if required
                  int addrBits = bits;
                  while (addrBits < 32) {
                    if (addrBits) strcat(pattern, ".");
                    strcat(pattern, "0");
                    addrBits += 8;
                  }

                  // Append the number of bits to match
                  char buf[4];
                  sprintf(buf, "/%d", bits);
                  strcat(pattern, buf);

                  // Append this pattern to the Hosts value
                  if (!newHosts.empty())
                    newHosts += ",";
                  newHosts += pattern;
                }
              }

              // Finally, save the Hosts value
              regKey.setString("Hosts", newHosts.c_str());
            } catch (std::exception&) {
              MsgBox(nullptr, "Unable to convert AuthHosts setting to Hosts format.",
                     MB_ICONWARNING | MB_OK);
            }
          } else {
            regKey.setString("Hosts", "+");
          }

          regKey.setBool("LocalHost", winvnc3.getBool("LoopbackOnly", false));
          // *** check AllowLoopback?

          if (winvnc3.getBool("AuthRequired", true))
            regKey.setString("SecurityTypes", "VncAuth");
          else
            regKey.setString("SecurityTypes", "None");

          int connectPriority = winvnc3.getInt("ConnectPriority", 0);
          regKey.setBool("DisconnectClients", connectPriority == 0);
          regKey.setBool("AlwaysShared", connectPriority == 1);
          regKey.setBool("NeverShared", connectPriority == 2);

        } catch(std::exception&) {
        }

        // Open the local, default-user settings
        allowProperties = true;
        try {
          RegKey userKey;
          userKey.openKey(winvnc3, "Default");
          vlog.info("Loading default prefs");
          LoadUserPrefs(userKey);
        } catch(std::exception& e) {
          vlog.error("Error reading Default settings:%s", e.what());
        }

        // Open the local, user-specific settings
        if (userSettings && !username.empty()) {
          try {
            RegKey userKey;
            userKey.openKey(winvnc3, username.c_str());
            vlog.info("Loading local user prefs");
            LoadUserPrefs(userKey);
          } catch(std::exception& e) {
            vlog.error("Error reading local User settings:%s", e.what());
          }

          // Open the user's own settings
          if (allowProperties) {
            try {
              RegKey userKey;
              userKey.openKey(HKEY_CURRENT_USER, "Software\\ORL\\WinVNC3");
              vlog.info("Loading global user prefs");
              LoadUserPrefs(userKey);
            } catch(std::exception& e) {
              vlog.error("Error reading global User settings:%s", e.what());
            }
          }
        }

        // Disable the Options menu item if appropriate
        regKey.setBool("DisableOptions", !allowProperties);
      }

      void LegacyPage::LoadUserPrefs(const RegKey& key)
      {
        regKey.setInt("PortNumber", key.getBool("SocketConnect") ? key.getInt("PortNumber", 5900) : 0);
        if (key.getBool("AutoPortSelect", false)) {
          MsgBox(nullptr, "The AutoPortSelect setting is not supported by this release."
                    "The port number will default to 5900.",
                    MB_ICONWARNING | MB_OK);
          regKey.setInt("PortNumber", 5900);
        }
        regKey.setInt("IdleTimeout", key.getInt("IdleTimeout", 0));

        regKey.setBool("RemoveWallpaper", key.getBool("RemoveWallpaper"));
        regKey.setBool("DisableEffects", key.getBool("DisableEffects"));

        if (key.getInt("QuerySetting", 2) != 2) {
          regKey.setBool("QueryConnect", key.getInt("QuerySetting") > 2);
          MsgBox(nullptr, "The QuerySetting option has been replaced by QueryConnect."
                 "Please see the documentation for details of the QueryConnect option.",
                 MB_ICONWARNING | MB_OK);
        }
        regKey.setInt("QueryTimeout", key.getInt("QueryTimeout", 10));

        std::vector<uint8_t> passwd;
        passwd = key.getBinary("Password");
        regKey.setBinary("Password", passwd.data(), passwd.size());

        bool enableInputs = key.getBool("InputsEnabled", true);
        regKey.setBool("AcceptKeyEvents", enableInputs);
        regKey.setBool("AcceptPointerEvents", enableInputs);
        regKey.setBool("AcceptCutText", enableInputs);
        regKey.setBool("SendCutText", enableInputs);

        switch (key.getInt("LockSetting", 0)) {
        case 0: regKey.setString("DisconnectAction", "None"); break;
        case 1: regKey.setString("DisconnectAction", "Lock"); break;
        case 2: regKey.setString("DisconnectAction", "Logoff"); break;
        };

        regKey.setBool("DisableLocalInputs", key.getBool("LocalInputsDisabled", false));

        // *** ignore polling preferences
        // PollUnderCursor, PollForeground, OnlyPollConsole, OnlyPollOnEvent
        regKey.setBool("UseHooks", !key.getBool("PollFullScreen", false));

        if (key.isValue("AllowShutdown"))
          MsgBox(nullptr, "The AllowShutdown option is not supported by this release.", MB_ICONWARNING | MB_OK);
        if (key.isValue("AllowEditClients"))
          MsgBox(nullptr, "The AllowEditClients option is not supported by this release.", MB_ICONWARNING | MB_OK);

        allowProperties = key.getBool("AllowProperties", allowProperties);
      }