Bläddra i källkod

Updating code to PuTTY 0.82

Source commit: ddf59fef3b75f5efff8bf82fecdd61ef49970fd2
Martin Prikryl 10 månader sedan
förälder
incheckning
25df2381f1

+ 34 - 1
source/Putty.cbproj

@@ -35,7 +35,7 @@
         <BCC_wamp>true</BCC_wamp>
         <BCC_wamp>true</BCC_wamp>
         <BCC_wasm>true</BCC_wasm>
         <BCC_wasm>true</BCC_wasm>
         <BCC_waus>false</BCC_waus>
         <BCC_waus>false</BCC_waus>
-        <BCC_wbbf>true</BCC_wbbf>
+        <BCC_wbbf>false</BCC_wbbf>
         <BCC_wccc>false</BCC_wccc>
         <BCC_wccc>false</BCC_wccc>
         <BCC_wcln>true</BCC_wcln>
         <BCC_wcln>true</BCC_wcln>
         <BCC_wcsu>false</BCC_wcsu>
         <BCC_wcsu>false</BCC_wcsu>
@@ -352,6 +352,9 @@
         <CppCompile Include="putty\stubs\null-seat.c">
         <CppCompile Include="putty\stubs\null-seat.c">
             <BuildOrder>100</BuildOrder>
             <BuildOrder>100</BuildOrder>
         </CppCompile>
         </CppCompile>
+        <CppCompile Include="putty\stubs\null-socket.c">
+            <BuildOrder>171</BuildOrder>
+        </CppCompile>
         <CppCompile Include="putty\utils\antispoof.c">
         <CppCompile Include="putty\utils\antispoof.c">
             <BuildOrder>77</BuildOrder>
             <BuildOrder>77</BuildOrder>
         </CppCompile>
         </CppCompile>
@@ -379,12 +382,18 @@
         <CppCompile Include="putty\utils\burnstr.c">
         <CppCompile Include="putty\utils\burnstr.c">
             <BuildOrder>151</BuildOrder>
             <BuildOrder>151</BuildOrder>
         </CppCompile>
         </CppCompile>
+        <CppCompile Include="putty\utils\burnwcs.c">
+            <BuildOrder>170</BuildOrder>
+        </CppCompile>
         <CppCompile Include="putty\utils\cert-expr.c">
         <CppCompile Include="putty\utils\cert-expr.c">
             <BuildOrder>147</BuildOrder>
             <BuildOrder>147</BuildOrder>
         </CppCompile>
         </CppCompile>
         <CppCompile Include="putty\utils\conf.c">
         <CppCompile Include="putty\utils\conf.c">
             <BuildOrder>82</BuildOrder>
             <BuildOrder>82</BuildOrder>
         </CppCompile>
         </CppCompile>
+        <CppCompile Include="putty\utils\conf_data.c">
+            <BuildOrder>167</BuildOrder>
+        </CppCompile>
         <CppCompile Include="putty\utils\conf_dest.c">
         <CppCompile Include="putty\utils\conf_dest.c">
             <BuildOrder>164</BuildOrder>
             <BuildOrder>164</BuildOrder>
         </CppCompile>
         </CppCompile>
@@ -394,12 +403,24 @@
         <CppCompile Include="putty\utils\ctrlparse.c">
         <CppCompile Include="putty\utils\ctrlparse.c">
             <BuildOrder>84</BuildOrder>
             <BuildOrder>84</BuildOrder>
         </CppCompile>
         </CppCompile>
+        <CppCompile Include="putty\utils\decode_utf8.c">
+            <BuildOrder>176</BuildOrder>
+        </CppCompile>
+        <CppCompile Include="putty\utils\decode_utf8_to_wchar.c">
+            <BuildOrder>175</BuildOrder>
+        </CppCompile>
+        <CppCompile Include="putty\utils\decode_utf8_to_wide_string.c">
+            <BuildOrder>172</BuildOrder>
+        </CppCompile>
         <CppCompile Include="putty\utils\default_description.c">
         <CppCompile Include="putty\utils\default_description.c">
             <BuildOrder>85</BuildOrder>
             <BuildOrder>85</BuildOrder>
         </CppCompile>
         </CppCompile>
         <CppCompile Include="putty\utils\dup_mb_to_wc.c">
         <CppCompile Include="putty\utils\dup_mb_to_wc.c">
             <BuildOrder>86</BuildOrder>
             <BuildOrder>86</BuildOrder>
         </CppCompile>
         </CppCompile>
+        <CppCompile Include="putty\utils\dup_wc_to_mb.c">
+            <BuildOrder>168</BuildOrder>
+        </CppCompile>
         <CppCompile Include="putty\utils\dupcat.c">
         <CppCompile Include="putty\utils\dupcat.c">
             <BuildOrder>148</BuildOrder>
             <BuildOrder>148</BuildOrder>
         </CppCompile>
         </CppCompile>
@@ -409,6 +430,15 @@
         <CppCompile Include="putty\utils\dupstr.c">
         <CppCompile Include="putty\utils\dupstr.c">
             <BuildOrder>152</BuildOrder>
             <BuildOrder>152</BuildOrder>
         </CppCompile>
         </CppCompile>
+        <CppCompile Include="putty\utils\dupwcs.c">
+            <BuildOrder>166</BuildOrder>
+        </CppCompile>
+        <CppCompile Include="putty\utils\encode_utf8.c">
+            <BuildOrder>174</BuildOrder>
+        </CppCompile>
+        <CppCompile Include="putty\utils\encode_wide_string_as_utf8.c">
+            <BuildOrder>173</BuildOrder>
+        </CppCompile>
         <CppCompile Include="putty\utils\host_ca_new_free.c">
         <CppCompile Include="putty\utils\host_ca_new_free.c">
             <BuildOrder>148</BuildOrder>
             <BuildOrder>148</BuildOrder>
         </CppCompile>
         </CppCompile>
@@ -433,6 +463,9 @@
         <CppCompile Include="putty\utils\log_proxy_stderr.c">
         <CppCompile Include="putty\utils\log_proxy_stderr.c">
             <BuildOrder>95</BuildOrder>
             <BuildOrder>95</BuildOrder>
         </CppCompile>
         </CppCompile>
+        <CppCompile Include="putty\utils\logeventf.c">
+            <BuildOrder>169</BuildOrder>
+        </CppCompile>
         <CppCompile Include="putty\utils\make_spr_sw_abort_static.c">
         <CppCompile Include="putty\utils\make_spr_sw_abort_static.c">
             <BuildOrder>153</BuildOrder>
             <BuildOrder>153</BuildOrder>
         </CppCompile>
         </CppCompile>

+ 33 - 12
source/core/PuttyIntf.cpp

@@ -198,15 +198,12 @@ static SeatPromptResult get_userpass_input(Seat * seat, prompts_t * p)
   try
   try
   {
   {
     UnicodeString Name = UTF8ToString(p->name);
     UnicodeString Name = UTF8ToString(p->name);
-    UnicodeString AName = Name;
-    TPromptKind PromptKind = SecureShell->IdentifyPromptKind(AName);
-    bool UTF8Prompt = (PromptKind != pkPassphrase);
 
 
     for (int Index = 0; Index < int(p->n_prompts); Index++)
     for (int Index = 0; Index < int(p->n_prompts); Index++)
     {
     {
       prompt_t * Prompt = p->prompts[Index];
       prompt_t * Prompt = p->prompts[Index];
       UnicodeString S;
       UnicodeString S;
-      if (UTF8Prompt)
+      if (p->utf8)
       {
       {
         S = UTF8ToString(Prompt->prompt);
         S = UTF8ToString(Prompt->prompt);
       }
       }
@@ -229,7 +226,7 @@ static SeatPromptResult get_userpass_input(Seat * seat, prompts_t * p)
       {
       {
         prompt_t * Prompt = p->prompts[Index];
         prompt_t * Prompt = p->prompts[Index];
         RawByteString S;
         RawByteString S;
-        if (UTF8Prompt)
+        if (p->utf8)
         {
         {
           S = RawByteString(UTF8String(Results->Strings[Index]));
           S = RawByteString(UTF8String(Results->Strings[Index]));
         }
         }
@@ -262,6 +259,13 @@ static void connection_fatal(Seat * seat, const char * message)
   SecureShell->PuttyFatalError(UnicodeString(AnsiString(message)));
   SecureShell->PuttyFatalError(UnicodeString(AnsiString(message)));
 }
 }
 //---------------------------------------------------------------------------
 //---------------------------------------------------------------------------
+static void nonfatal(Seat *, const char * message)
+{
+  // there's no place in our putty code, where this is called
+  DebugFail();
+  AppLog(UnicodeString(AnsiString(message)));
+}
+//---------------------------------------------------------------------------
 SeatPromptResult confirm_ssh_host_key(Seat * seat, const char * host, int port, const char * keytype,
 SeatPromptResult confirm_ssh_host_key(Seat * seat, const char * host, int port, const char * keytype,
   char * keystr, SeatDialogText *, HelpCtx,
   char * keystr, SeatDialogText *, HelpCtx,
   void (*DebugUsedArg(callback))(void *ctx, SeatPromptResult result), void * DebugUsedArg(ctx),
   void (*DebugUsedArg(callback))(void *ctx, SeatPromptResult result), void * DebugUsedArg(ctx),
@@ -434,6 +438,7 @@ static const SeatVtable ScpSeatVtable =
     nullseat_notify_remote_exit,
     nullseat_notify_remote_exit,
     nullseat_notify_remote_disconnect,
     nullseat_notify_remote_disconnect,
     connection_fatal,
     connection_fatal,
+    nonfatal,
     nullseat_update_specials_menu,
     nullseat_update_specials_menu,
     nullseat_get_ttymode,
     nullseat_get_ttymode,
     nullseat_set_busy_status,
     nullseat_set_busy_status,
@@ -473,6 +478,22 @@ int reg_override_winscp()
   return (PuttyRegistryMode != prmPass);
   return (PuttyRegistryMode != prmPass);
 }
 }
 //---------------------------------------------------------------------------
 //---------------------------------------------------------------------------
+void putty_registry_pass(bool enable)
+{
+  if (enable)
+  {
+    PuttyRegistrySection->Enter();
+    DebugAssert(PuttyRegistryMode == prmRedirect);
+    PuttyRegistryMode = prmPass;
+  }
+  else
+  {
+    DebugAssert(PuttyRegistryMode == prmPass);
+    PuttyRegistryMode = prmRedirect;
+    PuttyRegistrySection->Leave();
+  }
+}
+//---------------------------------------------------------------------------
 HKEY open_regkey_fn_winscp(bool Create, bool Write, HKEY Key, const char * Path, ...)
 HKEY open_regkey_fn_winscp(bool Create, bool Write, HKEY Key, const char * Path, ...)
 {
 {
   DebugUsedParam(Write);
   DebugUsedParam(Write);
@@ -692,7 +713,7 @@ TKeyType KeyType(UnicodeString FileName)
   DebugAssert(ktSSHCom == SSH_KEYTYPE_SSHCOM);
   DebugAssert(ktSSHCom == SSH_KEYTYPE_SSHCOM);
   DebugAssert(ktSSH2PublicOpenSSH == SSH_KEYTYPE_SSH2_PUBLIC_OPENSSH);
   DebugAssert(ktSSH2PublicOpenSSH == SSH_KEYTYPE_SSH2_PUBLIC_OPENSSH);
   UTF8String UtfFileName = UTF8String(FileName);
   UTF8String UtfFileName = UTF8String(FileName);
-  Filename * KeyFile = filename_from_str(UtfFileName.c_str());
+  Filename * KeyFile = filename_from_utf8(UtfFileName.c_str());
   TKeyType Result = (TKeyType)key_type(KeyFile);
   TKeyType Result = (TKeyType)key_type(KeyFile);
   filename_free(KeyFile);
   filename_free(KeyFile);
   return Result;
   return Result;
@@ -703,7 +724,7 @@ bool IsKeyEncrypted(TKeyType KeyType, const UnicodeString & FileName, UnicodeStr
   UTF8String UtfFileName = UTF8String(FileName);
   UTF8String UtfFileName = UTF8String(FileName);
   bool Result;
   bool Result;
   char * CommentStr = NULL;
   char * CommentStr = NULL;
-  Filename * KeyFile = filename_from_str(UtfFileName.c_str());
+  Filename * KeyFile = filename_from_utf8(UtfFileName.c_str());
   try
   try
   {
   {
     switch (KeyType)
     switch (KeyType)
@@ -746,7 +767,7 @@ bool IsKeyEncrypted(TKeyType KeyType, const UnicodeString & FileName, UnicodeStr
 TPrivateKey * LoadKey(TKeyType KeyType, const UnicodeString & FileName, const UnicodeString & Passphrase, UnicodeString & Error)
 TPrivateKey * LoadKey(TKeyType KeyType, const UnicodeString & FileName, const UnicodeString & Passphrase, UnicodeString & Error)
 {
 {
   UTF8String UtfFileName = UTF8String(FileName);
   UTF8String UtfFileName = UTF8String(FileName);
-  Filename * KeyFile = filename_from_str(UtfFileName.c_str());
+  Filename * KeyFile = filename_from_utf8(UtfFileName.c_str());
   struct ssh2_userkey * Ssh2Key = NULL;
   struct ssh2_userkey * Ssh2Key = NULL;
   const char * ErrorStr = NULL;
   const char * ErrorStr = NULL;
   AnsiString AnsiPassphrase = Passphrase;
   AnsiString AnsiPassphrase = Passphrase;
@@ -850,7 +871,7 @@ void AddCertificateToKey(TPrivateKey * PrivateKey, const UnicodeString & Certifi
   }
   }
 
 
   UTF8String UtfCertificateFileName = UTF8String(CertificateFileName);
   UTF8String UtfCertificateFileName = UTF8String(CertificateFileName);
-  Filename * CertFilename = filename_from_str(UtfCertificateFileName.c_str());
+  Filename * CertFilename = filename_from_utf8(UtfCertificateFileName.c_str());
 
 
   LoadedFile * CertLoadedFile;
   LoadedFile * CertLoadedFile;
   try
   try
@@ -938,7 +959,7 @@ void SaveKey(TKeyType KeyType, const UnicodeString & FileName,
   const UnicodeString & Passphrase, TPrivateKey * PrivateKey)
   const UnicodeString & Passphrase, TPrivateKey * PrivateKey)
 {
 {
   UTF8String UtfFileName = UTF8String(FileName);
   UTF8String UtfFileName = UTF8String(FileName);
-  Filename * KeyFile = filename_from_str(UtfFileName.c_str());
+  Filename * KeyFile = filename_from_utf8(UtfFileName.c_str());
   try
   try
   {
   {
     struct ssh2_userkey * Ssh2Key = reinterpret_cast<struct ssh2_userkey *>(PrivateKey);
     struct ssh2_userkey * Ssh2Key = reinterpret_cast<struct ssh2_userkey *>(PrivateKey);
@@ -990,7 +1011,7 @@ RawByteString LoadPublicKey(
 {
 {
   RawByteString Result;
   RawByteString Result;
   UTF8String UtfFileName = UTF8String(FileName);
   UTF8String UtfFileName = UTF8String(FileName);
-  Filename * KeyFile = filename_from_str(UtfFileName.c_str());
+  Filename * KeyFile = filename_from_utf8(UtfFileName.c_str());
   try
   try
   {
   {
     char * AlgorithmStr = NULL;
     char * AlgorithmStr = NULL;
@@ -1038,7 +1059,7 @@ bool __fastcall HasGSSAPI(UnicodeString CustomPath)
     ssh_gss_liblist * List = NULL;
     ssh_gss_liblist * List = NULL;
     try
     try
     {
     {
-      Filename * filename = filename_from_str(UTF8String(CustomPath).c_str());
+      Filename * filename = filename_from_utf8(UTF8String(CustomPath).c_str());
       conf_set_filename(conf, CONF_ssh_gss_custom, filename);
       conf_set_filename(conf, CONF_ssh_gss_custom, filename);
       filename_free(filename);
       filename_free(filename);
       List = ssh_gss_setup(conf, NULL);
       List = ssh_gss_setup(conf, NULL);

+ 4 - 4
source/core/SecureShell.cpp

@@ -243,15 +243,15 @@ Conf * __fastcall TSecureShell::StoreToConfig(TSessionData * Data, bool Simple)
     }
     }
     conf_set_int_int(conf, CONF_ssh_gsslist, g, pgsslib);
     conf_set_int_int(conf, CONF_ssh_gsslist, g, pgsslib);
   }
   }
-  Filename * GssLibCustomFileName = filename_from_str(UTF8String(Data->GssLibCustom).c_str());
+  Filename * GssLibCustomFileName = filename_from_utf8(UTF8String(Data->GssLibCustom).c_str());
   conf_set_filename(conf, CONF_ssh_gss_custom, GssLibCustomFileName);
   conf_set_filename(conf, CONF_ssh_gss_custom, GssLibCustomFileName);
   filename_free(GssLibCustomFileName);
   filename_free(GssLibCustomFileName);
 
 
-  Filename * AFileName = filename_from_str(UTF8String(Data->ResolvePublicKeyFile()).c_str());
+  Filename * AFileName = filename_from_utf8(UTF8String(Data->ResolvePublicKeyFile()).c_str());
   conf_set_filename(conf, CONF_keyfile, AFileName);
   conf_set_filename(conf, CONF_keyfile, AFileName);
   filename_free(AFileName);
   filename_free(AFileName);
 
 
-  AFileName = filename_from_str(UTF8String(ExpandEnvironmentVariables(Data->DetachedCertificate)).c_str());
+  AFileName = filename_from_utf8(UTF8String(ExpandEnvironmentVariables(Data->DetachedCertificate)).c_str());
   conf_set_filename(conf, CONF_detached_cert, AFileName);
   conf_set_filename(conf, CONF_detached_cert, AFileName);
   filename_free(AFileName);
   filename_free(AFileName);
 
 
@@ -2466,7 +2466,7 @@ UnicodeString TSecureShell::StoreHostKey(
   std::unique_ptr<THierarchicalStorage> Storage(GetHostKeyStorage());
   std::unique_ptr<THierarchicalStorage> Storage(GetHostKeyStorage());
   Storage->AccessMode = smReadWrite;
   Storage->AccessMode = smReadWrite;
   TValueRestorer<THierarchicalStorage *> StorageRestorer(PuttyStorage, Storage.get());
   TValueRestorer<THierarchicalStorage *> StorageRestorer(PuttyStorage, Storage.get());
-  store_host_key(AnsiString(Host).c_str(), Port, AnsiString(KeyType).c_str(), AnsiString(KeyStr).c_str());
+  store_host_key(FSeat, AnsiString(Host).c_str(), Port, AnsiString(KeyType).c_str(), AnsiString(KeyStr).c_str());
   return Storage->Source;
   return Storage->Source;
 }
 }
 //---------------------------------------------------------------------------
 //---------------------------------------------------------------------------

+ 1 - 1
source/core/SecureShell.h

@@ -129,6 +129,7 @@ protected:
   UnicodeString __fastcall FormatKeyStr(UnicodeString KeyStr);
   UnicodeString __fastcall FormatKeyStr(UnicodeString KeyStr);
   void ParseFingerprint(const UnicodeString & Fingerprint, UnicodeString & SignKeyType, UnicodeString & Hash);
   void ParseFingerprint(const UnicodeString & Fingerprint, UnicodeString & SignKeyType, UnicodeString & Hash);
   static Conf * __fastcall StoreToConfig(TSessionData * Data, bool Simple);
   static Conf * __fastcall StoreToConfig(TSessionData * Data, bool Simple);
+  TPromptKind __fastcall IdentifyPromptKind(UnicodeString & Name);
 
 
 public:
 public:
   __fastcall TSecureShell(TSessionUI * UI, TSessionData * SessionData,
   __fastcall TSecureShell(TSessionUI * UI, TSessionData * SessionData,
@@ -162,7 +163,6 @@ public:
   void __fastcall UpdateSocket(SOCKET value, bool Enable);
   void __fastcall UpdateSocket(SOCKET value, bool Enable);
   void __fastcall UpdatePortFwdSocket(SOCKET value, bool Enable);
   void __fastcall UpdatePortFwdSocket(SOCKET value, bool Enable);
   void __fastcall PuttyFatalError(UnicodeString Error);
   void __fastcall PuttyFatalError(UnicodeString Error);
-  TPromptKind __fastcall IdentifyPromptKind(UnicodeString & Name);
   bool __fastcall PromptUser(bool ToServer,
   bool __fastcall PromptUser(bool ToServer,
     UnicodeString AName, bool NameRequired,
     UnicodeString AName, bool NameRequired,
     UnicodeString Instructions, bool InstructionsRequired,
     UnicodeString Instructions, bool InstructionsRequired,

+ 1 - 1
source/core/SessionData.cpp

@@ -2072,7 +2072,7 @@ bool __fastcall TSessionData::IsSensitiveOption(const UnicodeString & Option, co
   }
   }
   else if (SameText(Option, PRIVATEKEY_SWITCH))
   else if (SameText(Option, PRIVATEKEY_SWITCH))
   {
   {
-    Filename * AFilename = filename_from_str(UTF8String(Value).c_str());
+    Filename * AFilename = filename_from_utf8(UTF8String(Value).c_str());
     Result = (in_memory_key_data(AFilename) != NULL);
     Result = (in_memory_key_data(AFilename) != NULL);
     filename_free(AFilename);
     filename_free(AFilename);
   }
   }

+ 26 - 0
source/putty/conf.h

@@ -1286,3 +1286,29 @@ CONF_OPTION(winclass,
     DEFAULT_STR(""),
     DEFAULT_STR(""),
     SAVE_KEYWORD("WindowClass"),
     SAVE_KEYWORD("WindowClass"),
 )
 )
+
+/* WINSCP BEGIN */
+CONF_OPTION(connect_timeout,
+    VALUE_TYPE(INT),
+    NOT_SAVED,
+)
+CONF_OPTION(sndbuf,
+    VALUE_TYPE(INT),
+    NOT_SAVED,
+)
+CONF_OPTION(srcaddr,
+    VALUE_TYPE(STR),
+    DEFAULT_STR(""),
+    NOT_SAVED,
+)
+CONF_OPTION(force_remote_cmd2,
+    VALUE_TYPE(BOOL),
+    DEFAULT_BOOL(false),
+    NOT_SAVED,
+)
+CONF_OPTION(change_password,
+    VALUE_TYPE(BOOL),
+    DEFAULT_BOOL(false),
+    NOT_SAVED,
+)
+/* WINSCP END */

+ 520 - 0
source/putty/conf.winscp.h

@@ -0,0 +1,520 @@
+/*
+ * Master list of configuration options living in the Conf data
+ * structure.
+ *
+ * Each CONF_OPTION directive defines a single CONF_foo primary key in
+ * Conf, and can be equipped with the following properties:
+ *
+ *  - VALUE_TYPE: the type of data associated with that key
+ *  - SUBKEY_TYPE: if the primary key goes with a subkey (that is, the
+ *    primary key identifies some mapping from subkeys to values), the
+ *    data type of the subkey
+ *  - DEFAULT_INT, DEFAULT_STR, DEFAULT_BOOL: the default value for
+ *    the key, if no save data is available. Must match VALUE_TYPE, if
+ *    the key has no subkey. Otherwise, no default is permitted, and
+ *    the default value of the mapping is assumed to be empty (and if
+ *    not, then LOAD_CUSTOM code must override that).
+ *  - SAVE_KEYWORD: the keyword used for the option in the Windows
+ *    registry or ~/.putty/sessions save files.
+ *  - STORAGE_ENUM: for int-typed settings with no subkeys, this
+ *    identifies an enumeration in conf-enums.h which maps internal
+ *    values of the setting in the Conf to values in the saved data.
+ *  - LOAD_CUSTOM, SAVE_CUSTOM: suppress automated loading or saving
+ *    (respectively) of this setting, in favour of manual code in
+ *    settings.c load_open_settings() or save_open_settings()
+ *    respectively.
+ *  - NOT_SAVED: indicate that this setting is not part of saved
+ *    session data at all.
+ */
+
+CONF_OPTION(host, NONE, STR, (int)"", false, false, false, "HostName", NULL)
+/* default value depends on the value of CONF_protocol */
+CONF_OPTION(port, NONE, INT, 0, false, true, false, "PortNumber", NULL)
+/* PROT_SSH, PROT_TELNET etc */
+/*
+ * Notionally SAVE_KEYWORD("Protocol"), but saving/loading is handled by
+ * custom code because the stored value is a string representation
+ * of the protocol name.
+ */
+CONF_OPTION(protocol, NONE, INT, 0, true, true, false, NULL, NULL)
+CONF_OPTION(addressfamily, NONE, INT, ADDRTYPE_UNSPEC, false, false, false, "AddressFamily", &conf_enum_addressfamily)
+CONF_OPTION(close_on_exit, NONE, INT, AUTO, false, false, false, "CloseOnExit", &conf_enum_off_auto_on)
+CONF_OPTION(warn_on_close, NONE, BOOL, (int)true, false, false, false, "WarnOnClose", NULL)
+/* in seconds */
+/*
+ * Saving/loading is handled by custom code because for historical
+ * reasons this value corresponds to two save keywords,
+ * "PingInterval" (measured in minutes) and "PingIntervalSecs"
+ * (measured in seconds), which are added together on loading.
+ * Rationale: the value was once measured in minutes, and the
+ * seconds field was added later.
+ */
+CONF_OPTION(ping_interval, NONE, INT, 0, true, true, false, NULL, NULL)
+CONF_OPTION(tcp_nodelay, NONE, BOOL, (int)true, false, false, false, "TCPNoDelay", NULL)
+CONF_OPTION(tcp_keepalives, NONE, BOOL, (int)false, false, false, false, "TCPKeepalives", NULL)
+/* logical host being contacted, for host key check */
+CONF_OPTION(loghost, NONE, STR, (int)"", false, false, false, "LogHost", NULL)
+
+/* Proxy options */
+CONF_OPTION(proxy_exclude_list, NONE, STR, (int)"", false, false, false, "ProxyExcludeList", NULL)
+CONF_OPTION(proxy_dns, NONE, INT, AUTO, false, false, false, "ProxyDNS", &conf_enum_off_auto_on)
+CONF_OPTION(even_proxy_localhost, NONE, BOOL, (int)false, false, false, false, "ProxyLocalhost", NULL)
+/* PROXY_NONE, PROXY_SOCKS4, ... */
+/*
+ * Custom load code: there was an earlier keyword "ProxyType"
+ * using a different enumeration, in which SOCKS4 and SOCKS5
+ * shared a value, and a second keyword "ProxySOCKSVersion"
+ * disambiguated.
+ */
+CONF_OPTION(proxy_type, NONE, INT, 0, false, true, false, "ProxyMethod", &conf_enum_proxy_type)
+CONF_OPTION(proxy_host, NONE, STR, (int)"proxy", false, false, false, "ProxyHost", NULL)
+CONF_OPTION(proxy_port, NONE, INT, 80, false, false, false, "ProxyPort", NULL)
+CONF_OPTION(proxy_username, NONE, STR, (int)"", false, false, false, "ProxyUsername", NULL)
+CONF_OPTION(proxy_password, NONE, STR, (int)"", false, false, false, "ProxyPassword", NULL)
+CONF_OPTION(proxy_telnet_command, NONE, STR, (int)"connect %host %port\\n", false, false, false, "ProxyTelnetCommand", NULL)
+CONF_OPTION(proxy_log_to_term, NONE, INT, FORCE_OFF, false, false, false, "ProxyLogToTerm", &conf_enum_on_off_auto)
+
+/* SSH options */
+CONF_OPTION(remote_cmd, NONE, STR_AMBI, (int)"", false, false, false, "RemoteCommand", NULL)
+/*
+ * Fallback command to try to run if remote_cmd fails. Only set
+ * internally by PSCP and PSFTP (so that they can try multiple
+ * methods of running an SFTP server at the remote end); never set
+ * by user configuration, or loaded or saved.
+ */
+CONF_OPTION(remote_cmd2, NONE, STR_AMBI, (int)"", false, false, true, NULL, NULL)
+CONF_OPTION(nopty, NONE, BOOL, (int)false, false, false, false, "NoPTY", NULL)
+CONF_OPTION(compression, NONE, BOOL, (int)false, false, false, false, "Compression", NULL)
+/* indices in preference order: 0,...,KEX_MAX-1
+ * (lower is more preferred) */
+/* KEX_* enum values */
+/* necessary for preference lists */
+CONF_OPTION(ssh_kexlist, INT, INT, 0, true, true, false, NULL, NULL)
+/* indices in preference order: 0,...,HK_MAX-1
+ * (lower is more preferred) */
+/* HK_* enum values */
+/* necessary for preference lists */
+CONF_OPTION(ssh_hklist, INT, INT, 0, true, true, false, NULL, NULL)
+CONF_OPTION(ssh_prefer_known_hostkeys, NONE, BOOL, (int)true, false, false, false, "PreferKnownHostKeys", NULL)
+/* in minutes */
+CONF_OPTION(ssh_rekey_time, NONE, INT, 60, false, false, false, "RekeyTime", NULL)
+/* string encoding e.g. "100K", "2M", "1G" */
+CONF_OPTION(ssh_rekey_data, NONE, STR, (int)"1G", false, false, false, "RekeyBytes", NULL)
+CONF_OPTION(tryagent, NONE, BOOL, (int)true, false, false, false, "TryAgent", NULL)
+CONF_OPTION(agentfwd, NONE, BOOL, (int)false, false, false, false, "AgentFwd", NULL)
+/* allow username switching in SSH-2 */
+CONF_OPTION(change_username, NONE, BOOL, (int)false, false, false, false, "ChangeUsername", NULL)
+/* indices in preference order: 0,...,CIPHER_MAX-1
+ * (lower is more preferred) */
+/* CIPHER_* enum values */
+/* necessary for preference lists */
+CONF_OPTION(ssh_cipherlist, INT, INT, 0, true, true, false, NULL, NULL)
+CONF_OPTION(keyfile, NONE, FILENAME, 0, false, false, false, "PublicKeyFile", NULL)
+CONF_OPTION(detached_cert, NONE, FILENAME, 0, false, false, false, "DetachedCertificate", NULL)
+CONF_OPTION(auth_plugin, NONE, STR, (int)"", false, false, false, "AuthPlugin", NULL)
+/*
+ * Which SSH protocol to use.
+ *
+ * For historical reasons, the current legal values for CONF_sshprot
+ * are:
+ *  0 = SSH-1 only
+ *  3 = SSH-2 only
+ *
+ * We used to also support
+ *  1 = SSH-1 with fallback to SSH-2
+ *  2 = SSH-2 with fallback to SSH-1
+ *
+ * and we continue to use 0/3 in storage formats rather than the more
+ * obvious 1/2 to avoid surprises if someone saves a session and later
+ * downgrades PuTTY. So it's easier to use these numbers internally too.
+ */
+CONF_OPTION(sshprot, NONE, INT, 3, false, false, false, "SshProt", &conf_enum_ssh_protocol)
+/*
+ * This means that we promise never to open any channel other
+ * than the main one, which means it can safely use a very large
+ * window in SSH-2.
+ *
+ * Only ever set internally by file transfer tools; never set by
+ * user configuration, or loaded or saved.
+ */
+CONF_OPTION(ssh_simple, NONE, BOOL, (int)false, false, false, true, NULL, NULL)
+CONF_OPTION(ssh_connection_sharing, NONE, BOOL, (int)false, false, false, false, "ConnectionSharing", NULL)
+CONF_OPTION(ssh_connection_sharing_upstream, NONE, BOOL, (int)true, false, false, false, "ConnectionSharingUpstream", NULL)
+CONF_OPTION(ssh_connection_sharing_downstream, NONE, BOOL, (int)true, false, false, false, "ConnectionSharingDownstream", NULL)
+/*
+ * Manually configured host keys to accept regardless of the state
+ * of the host key cache.
+ *
+ * This is conceptually a set rather than a dictionary: every
+ * value in this map is the empty string, and the set of subkeys
+ * that exist is the important data.
+ */
+/* necessary for mappings */
+CONF_OPTION(ssh_manual_hostkeys, STR, STR, 0, true, true, false, NULL, NULL)
+/* "des-cbc" unrecommended SSH-2 cipher */
+CONF_OPTION(ssh2_des_cbc, NONE, BOOL, (int)false, false, false, false, "SSH2DES", NULL)
+/* bypass "ssh-userauth" (SSH-2 only) */
+CONF_OPTION(ssh_no_userauth, NONE, BOOL, (int)false, false, false, false, "SshNoAuth", NULL)
+/* disable trivial types of auth */
+CONF_OPTION(ssh_no_trivial_userauth, NONE, BOOL, (int)false, false, false, false, "SshNoTrivialAuth", NULL)
+/* show USERAUTH_BANNERs (SSH-2 only) */
+CONF_OPTION(ssh_show_banner, NONE, BOOL, (int)true, false, false, false, "SshBanner", NULL)
+CONF_OPTION(try_tis_auth, NONE, BOOL, (int)false, false, false, false, "AuthTIS", NULL)
+CONF_OPTION(try_ki_auth, NONE, BOOL, (int)true, false, false, false, "AuthKI", NULL)
+/* attempt gssapi via ssh userauth */
+/* under #ifndef NO_GSSAPI */
+CONF_OPTION(try_gssapi_auth, NONE, BOOL, 0, true, true, false, NULL, NULL)
+/* attempt gssapi via ssh kex */
+/* under #ifndef NO_GSSAPI */
+CONF_OPTION(try_gssapi_kex, NONE, BOOL, 0, true, true, false, NULL, NULL)
+/* forward tgt via gss */
+/* under #ifndef NO_GSSAPI */
+CONF_OPTION(gssapifwd, NONE, BOOL, 0, true, true, false, NULL, NULL)
+/* KEXGSS refresh interval (mins) */
+/* under #ifndef NO_GSSAPI */
+CONF_OPTION(gssapirekey, NONE, INT, 0, true, true, false, NULL, NULL)
+/* indices in preference order: 0,...,ngsslibs
+ * (lower is more preferred; ngsslibs is a platform-
+ * dependent value) */
+/* indices of GSSAPI lib types (platform-dependent) */
+/* necessary for preference lists, also this
+ * setting is under #ifndef NO_GSSAPI */
+CONF_OPTION(ssh_gsslist, INT, INT, 0, true, true, false, NULL, NULL)
+/* under #ifndef NO_GSSAPI */
+CONF_OPTION(ssh_gss_custom, NONE, FILENAME, 0, true, true, false, NULL, NULL)
+/* run a subsystem rather than a command */
+/*
+ * Only set internally by PSCP and PSFTP; never set by user
+ * configuration, or loaded or saved.
+ */
+CONF_OPTION(ssh_subsys, NONE, BOOL, (int)false, false, false, true, NULL, NULL)
+/* fallback to go with remote_cmd2 */
+/*
+ * Only set internally by PSCP and PSFTP; never set by user
+ * configuration, or loaded or saved.
+ */
+CONF_OPTION(ssh_subsys2, NONE, BOOL, (int)false, false, false, true, NULL, NULL)
+/* avoid running a shell */
+CONF_OPTION(ssh_no_shell, NONE, BOOL, (int)false, false, false, false, "SshNoShell", NULL)
+/* host to connect to in `nc' mode */
+/*
+ * Only set by the '-nc' command-line option and by the SSH proxy
+ * code. There's no GUI config option for this, and therefore it's
+ * also never loaded or saved.
+ */
+CONF_OPTION(ssh_nc_host, NONE, STR, (int)"", false, false, true, NULL, NULL)
+/* port to connect to in `nc' mode */
+/*
+ * Only set by the '-nc' command-line option and by the SSH proxy
+ * code. There's no GUI config option for this, and therefore it's
+ * also never loaded or saved.
+ */
+CONF_OPTION(ssh_nc_port, NONE, INT, 0, false, false, true, NULL, NULL)
+
+/* Telnet options */
+CONF_OPTION(termtype, NONE, STR, (int)"xterm", false, false, false, "TerminalType", NULL)
+CONF_OPTION(termspeed, NONE, STR, (int)"38400,38400", false, false, false, "TerminalSpeed", NULL)
+/*
+ * The full set of permitted subkeys is listed in
+ * ssh/ttymode-list.h, as the first parameter of each TTYMODE_CHAR
+ * or TTYMODE_FLAG macro.
+ *
+ * The permitted value strings are:
+ *
+ *  - "N" means do not include a record for this mode at all in
+ *    the terminal mode data in the "pty-req" channel request.
+ *    Corresponds to setting the mode to 'Nothing' in the GUI.
+ *  - "A" means use PuTTY's automatic default, matching the
+ *    settings for GUI PuTTY's terminal window or Unix Plink's
+ *    controlling tty. Corresponds to setting 'Auto' in the GUI.
+ *  - "V" followed by further string data means send a custom
+ *    value to the SSH server. Values are as documented in the
+ *    manual.
+ */
+/* necessary for mappings */
+CONF_OPTION(ttymodes, STR, STR, 0, true, true, false, NULL, NULL)
+/* environment variable name */
+/* environment variable value */
+/* necessary for mappings */
+CONF_OPTION(environmt, STR, STR, 0, true, true, false, NULL, NULL)
+CONF_OPTION(username, NONE, STR_AMBI, (int)"", false, false, false, "UserName", NULL)
+CONF_OPTION(username_from_env, NONE, BOOL, (int)false, false, false, false, "UserNameFromEnvironment", NULL)
+CONF_OPTION(localusername, NONE, STR, (int)"", false, false, false, "LocalUserName", NULL)
+CONF_OPTION(rfc_environ, NONE, BOOL, (int)false, false, false, false, "RFCEnviron", NULL)
+CONF_OPTION(passive_telnet, NONE, BOOL, (int)false, false, false, false, "PassiveTelnet", NULL)
+
+/* Serial port options */
+CONF_OPTION(serline, NONE, STR, (int)"", false, false, false, "SerialLine", NULL)
+CONF_OPTION(serspeed, NONE, INT, 9600, false, false, false, "SerialSpeed", NULL)
+CONF_OPTION(serdatabits, NONE, INT, 8, false, false, false, "SerialDataBits", NULL)
+CONF_OPTION(serstopbits, NONE, INT, 2, false, false, false, "SerialStopHalfbits", NULL)
+CONF_OPTION(serparity, NONE, INT, SER_PAR_NONE, false, false, false, "SerialParity", &conf_enum_serparity)
+CONF_OPTION(serflow, NONE, INT, SER_FLOW_XONXOFF, false, false, false, "SerialFlowControl", &conf_enum_serflow)
+
+/* SUPDUP options */
+CONF_OPTION(supdup_location, NONE, STR, (int)"The Internet", false, false, false, "SUPDUPLocation", NULL)
+CONF_OPTION(supdup_ascii_set, NONE, INT, SUPDUP_CHARSET_ASCII, false, false, false, "SUPDUPCharset", &conf_enum_supdup_charset)
+CONF_OPTION(supdup_more, NONE, BOOL, (int)false, false, false, false, "SUPDUPMoreProcessing", NULL)
+CONF_OPTION(supdup_scroll, NONE, BOOL, (int)false, false, false, false, "SUPDUPScrolling", NULL)
+
+/* Keyboard options */
+CONF_OPTION(bksp_is_delete, NONE, BOOL, (int)true, false, false, false, "BackspaceIsDelete", NULL)
+CONF_OPTION(rxvt_homeend, NONE, BOOL, (int)false, false, false, false, "RXVTHomeEnd", NULL)
+CONF_OPTION(funky_type, NONE, INT, FUNKY_TILDE, false, false, false, "LinuxFunctionKeys", &conf_enum_funky_type)
+CONF_OPTION(sharrow_type, NONE, INT, SHARROW_APPLICATION, false, false, false, "ShiftedArrowKeys", &conf_enum_sharrow_type)
+/* totally disable app cursor keys */
+CONF_OPTION(no_applic_c, NONE, BOOL, (int)false, false, false, false, "NoApplicationCursors", NULL)
+/* totally disable app keypad */
+CONF_OPTION(no_applic_k, NONE, BOOL, (int)false, false, false, false, "NoApplicationKeys", NULL)
+/* totally disable mouse reporting */
+CONF_OPTION(no_mouse_rep, NONE, BOOL, (int)false, false, false, false, "NoMouseReporting", NULL)
+/* disable remote resizing */
+CONF_OPTION(no_remote_resize, NONE, BOOL, (int)false, false, false, false, "NoRemoteResize", NULL)
+/* disable alternate screen */
+CONF_OPTION(no_alt_screen, NONE, BOOL, (int)false, false, false, false, "NoAltScreen", NULL)
+/* disable remote retitling */
+CONF_OPTION(no_remote_wintitle, NONE, BOOL, (int)false, false, false, false, "NoRemoteWinTitle", NULL)
+/* disable ESC[3J */
+CONF_OPTION(no_remote_clearscroll, NONE, BOOL, (int)false, false, false, false, "NoRemoteClearScroll", NULL)
+/* disable destructive backspace */
+CONF_OPTION(no_dbackspace, NONE, BOOL, (int)false, false, false, false, "NoDBackspace", NULL)
+/* disable remote charset config */
+CONF_OPTION(no_remote_charset, NONE, BOOL, (int)false, false, false, false, "NoRemoteCharset", NULL)
+/* handling of remote window title queries */
+/* older versions had a boolean "NoRemoteQTitle"
+ * before we ended up with three options */
+CONF_OPTION(remote_qtitle_action, NONE, INT, 0, false, true, false, "RemoteQTitleAction", &conf_enum_remote_qtitle_action)
+CONF_OPTION(app_cursor, NONE, BOOL, (int)false, false, false, false, "ApplicationCursorKeys", NULL)
+CONF_OPTION(app_keypad, NONE, BOOL, (int)false, false, false, false, "ApplicationKeypad", NULL)
+CONF_OPTION(nethack_keypad, NONE, BOOL, (int)false, false, false, false, "NetHackKeypad", NULL)
+CONF_OPTION(telnet_keyboard, NONE, BOOL, (int)false, false, false, false, "TelnetKey", NULL)
+CONF_OPTION(telnet_newline, NONE, BOOL, (int)true, false, false, false, "TelnetRet", NULL)
+/* is it special? */
+CONF_OPTION(alt_f4, NONE, BOOL, (int)true, false, false, false, "AltF4", NULL)
+/* is it special? */
+CONF_OPTION(alt_space, NONE, BOOL, (int)false, false, false, false, "AltSpace", NULL)
+/* is it special? */
+CONF_OPTION(alt_only, NONE, BOOL, (int)false, false, false, false, "AltOnly", NULL)
+CONF_OPTION(localecho, NONE, INT, AUTO, false, false, false, "LocalEcho", &conf_enum_on_off_auto)
+CONF_OPTION(localedit, NONE, INT, AUTO, false, false, false, "LocalEdit", &conf_enum_on_off_auto)
+CONF_OPTION(alwaysontop, NONE, BOOL, (int)false, false, false, false, "AlwaysOnTop", NULL)
+CONF_OPTION(fullscreenonaltenter, NONE, BOOL, (int)false, false, false, false, "FullScreenOnAltEnter", NULL)
+CONF_OPTION(scroll_on_key, NONE, BOOL, (int)false, false, false, false, "ScrollOnKey", NULL)
+CONF_OPTION(scroll_on_disp, NONE, BOOL, (int)true, false, false, false, "ScrollOnDisp", NULL)
+CONF_OPTION(erase_to_scrollback, NONE, BOOL, (int)true, false, false, false, "EraseToScrollback", NULL)
+CONF_OPTION(compose_key, NONE, BOOL, (int)false, false, false, false, "ComposeKey", NULL)
+CONF_OPTION(ctrlaltkeys, NONE, BOOL, (int)true, false, false, false, "CtrlAltKeys", NULL)
+/* under #ifdef OSX_META_KEY_CONFIG */
+CONF_OPTION(osx_option_meta, NONE, BOOL, 0, true, true, false, NULL, NULL)
+/* under #ifdef OSX_META_KEY_CONFIG */
+CONF_OPTION(osx_command_meta, NONE, BOOL, 0, true, true, false, NULL, NULL)
+/* initial window title */
+CONF_OPTION(wintitle, NONE, STR, (int)"", false, false, false, "WinTitle", NULL)
+/* Terminal options */
+CONF_OPTION(savelines, NONE, INT, 2000, false, false, false, "ScrollbackLines", NULL)
+CONF_OPTION(dec_om, NONE, BOOL, (int)false, false, false, false, "DECOriginMode", NULL)
+CONF_OPTION(wrap_mode, NONE, BOOL, (int)true, false, false, false, "AutoWrapMode", NULL)
+CONF_OPTION(lfhascr, NONE, BOOL, (int)false, false, false, false, "LFImpliesCR", NULL)
+CONF_OPTION(cursor_type, NONE, INT, 0, false, false, false, "CurType", &conf_enum_cursor_type)
+CONF_OPTION(blink_cur, NONE, BOOL, (int)false, false, false, false, "BlinkCur", NULL)
+CONF_OPTION(beep, NONE, INT, BELL_DEFAULT, false, false, false, "Beep", &conf_enum_beep)
+CONF_OPTION(beep_ind, NONE, INT, B_IND_DISABLED, false, false, false, "BeepInd", &conf_enum_beep_indication)
+/* bell overload protection active? */
+CONF_OPTION(bellovl, NONE, BOOL, (int)true, false, false, false, "BellOverload", NULL)
+/* number of bells to cause overload */
+CONF_OPTION(bellovl_n, NONE, INT, 5, false, false, false, "BellOverloadN", NULL)
+/* time interval for overload (ticks) */
+/*
+ * Loading and saving is done in custom code because the format is
+ * platform-dependent for historical reasons: on Unix, the stored
+ * value is multiplied by 1000. (And since TICKSPERSEC=1000 on
+ * that platform, it means the stored value is interpreted in
+ * microseconds.)
+ */
+CONF_OPTION(bellovl_t, NONE, INT, 0, true, true, false, NULL, NULL)
+/* period of silence to re-enable bell (s) */
+/*
+ * Loading and saving is done in custom code because the format is
+ * platform-dependent for historical reasons: on Unix, the stored
+ * value is multiplied by 1000. (And since TICKSPERSEC=1000 on
+ * that platform, it means the stored value is interpreted in
+ * microseconds.)
+ */
+CONF_OPTION(bellovl_s, NONE, INT, 0, true, true, false, NULL, NULL)
+CONF_OPTION(bell_wavefile, NONE, FILENAME, 0, false, false, false, "BellWaveFile", NULL)
+CONF_OPTION(scrollbar, NONE, BOOL, (int)true, false, false, false, "ScrollBar", NULL)
+CONF_OPTION(scrollbar_in_fullscreen, NONE, BOOL, (int)false, false, false, false, "ScrollBarFullScreen", NULL)
+CONF_OPTION(resize_action, NONE, INT, RESIZE_TERM, false, false, false, "LockSize", &conf_enum_resize_effect)
+CONF_OPTION(bce, NONE, BOOL, (int)true, false, false, false, "BCE", NULL)
+CONF_OPTION(blinktext, NONE, BOOL, (int)false, false, false, false, "BlinkText", NULL)
+CONF_OPTION(win_name_always, NONE, BOOL, (int)true, false, false, false, "WinNameAlways", NULL)
+CONF_OPTION(width, NONE, INT, 80, false, false, false, "TermWidth", NULL)
+CONF_OPTION(height, NONE, INT, 24, false, false, false, "TermHeight", NULL)
+CONF_OPTION(font, NONE, FONT, 0, false, false, false, "Font", NULL)
+CONF_OPTION(font_quality, NONE, INT, FQ_DEFAULT, false, false, false, "FontQuality", &conf_enum_font_quality)
+CONF_OPTION(logfilename, NONE, FILENAME, 0, false, false, false, "LogFileName", NULL)
+CONF_OPTION(logtype, NONE, INT, LGTYP_NONE, false, false, false, "LogType", &conf_enum_log_type)
+CONF_OPTION(logxfovr, NONE, INT, LGXF_ASK, false, false, false, "LogFileClash", &conf_enum_log_to_existing_file)
+CONF_OPTION(logflush, NONE, BOOL, (int)true, false, false, false, "LogFlush", NULL)
+CONF_OPTION(logheader, NONE, BOOL, (int)true, false, false, false, "LogHeader", NULL)
+CONF_OPTION(logomitpass, NONE, BOOL, (int)true, false, false, false, "SSHLogOmitPasswords", NULL)
+CONF_OPTION(logomitdata, NONE, BOOL, (int)false, false, false, false, "SSHLogOmitData", NULL)
+CONF_OPTION(hide_mouseptr, NONE, BOOL, (int)false, false, false, false, "HideMousePtr", NULL)
+CONF_OPTION(sunken_edge, NONE, BOOL, (int)false, false, false, false, "SunkenEdge", NULL)
+/* in pixels */
+CONF_OPTION(window_border, NONE, INT, 1, false, false, false, "WindowBorder", NULL)
+CONF_OPTION(answerback, NONE, STR, (int)"PuTTY", false, false, false, "Answerback", NULL)
+CONF_OPTION(printer, NONE, STR, (int)"", false, false, false, "Printer", NULL)
+CONF_OPTION(no_arabicshaping, NONE, BOOL, (int)false, false, false, false, "DisableArabicShaping", NULL)
+CONF_OPTION(no_bidi, NONE, BOOL, (int)false, false, false, false, "DisableBidi", NULL)
+CONF_OPTION(no_bracketed_paste, NONE, BOOL, (int)false, false, false, false, "DisableBracketedPaste", NULL)
+
+/* Colour options */
+CONF_OPTION(ansi_colour, NONE, BOOL, (int)true, false, false, false, "ANSIColour", NULL)
+CONF_OPTION(xterm_256_colour, NONE, BOOL, (int)true, false, false, false, "Xterm256Colour", NULL)
+CONF_OPTION(true_colour, NONE, BOOL, (int)true, false, false, false, "TrueColour", NULL)
+CONF_OPTION(system_colour, NONE, BOOL, (int)false, false, false, false, "UseSystemColours", NULL)
+CONF_OPTION(try_palette, NONE, BOOL, (int)false, false, false, false, "TryPalette", NULL)
+CONF_OPTION(bold_style, NONE, INT, 2, false, false, false, "BoldAsColour", &conf_enum_bold_style)
+/*
+ * Subkeys in this setting are indexed based on the CONF_COLOUR_*
+ * enum values in putty.h. But each subkey identifies just one
+ * component of the RGB value. Subkey 3*a+b identifies colour #a,
+ * channel #b, where channels 0,1,2 mean R,G,B respectively.
+ *
+ * Values are 8-bit integers.
+ */
+/* necessary for mappings */
+CONF_OPTION(colours, INT, INT, 0, true, true, false, NULL, NULL)
+
+/* Selection options */
+CONF_OPTION(mouse_is_xterm, NONE, INT, 0, false, false, false, "MouseIsXterm", &conf_enum_mouse_buttons)
+CONF_OPTION(rect_select, NONE, BOOL, (int)false, false, false, false, "RectSelect", NULL)
+CONF_OPTION(paste_controls, NONE, BOOL, (int)false, false, false, false, "PasteControls", NULL)
+CONF_OPTION(rawcnp, NONE, BOOL, (int)false, false, false, false, "RawCNP", NULL)
+CONF_OPTION(utf8linedraw, NONE, BOOL, (int)false, false, false, false, "UTF8linedraw", NULL)
+CONF_OPTION(rtf_paste, NONE, BOOL, (int)false, false, false, false, "PasteRTF", NULL)
+CONF_OPTION(mouse_override, NONE, BOOL, (int)true, false, false, false, "MouseOverride", NULL)
+/* ASCII character codes (literally, just 00-7F) */
+/* arbitrary equivalence-class value for that char */
+/* necessary for mappings */
+CONF_OPTION(wordness, INT, INT, 0, true, true, false, NULL, NULL)
+/*
+ * What clipboard (if any) to copy text to as soon as it's
+ * selected with the mouse.
+ */
+/* platform-dependent bool-valued
+ * macro */
+CONF_OPTION(mouseautocopy, NONE, BOOL, (int)CLIPUI_DEFAULT_AUTOCOPY, false, false, false, "MouseAutocopy", NULL)
+/* clipboard used by one-mouse-click paste actions */
+/*
+ * SAVE_KEYWORD("MousePaste"), but loading and saving is done by
+ * custom code, because the saved value is a string, and also sets
+ * CONF_mousepaste_custom
+ */
+CONF_OPTION(mousepaste, NONE, INT, 0, true, true, false, NULL, NULL)
+/* clipboard used by Ctrl+Ins and Shift+Ins */
+/*
+ * SAVE_KEYWORD("CtrlShiftIns"), but loading and saving is done by
+ * custom code, because the saved value is a string, and also sets
+ * CONF_ctrlshiftins_custom
+ */
+CONF_OPTION(ctrlshiftins, NONE, INT, 0, true, true, false, NULL, NULL)
+/* clipboard used by Ctrl+Shift+C and Ctrl+Shift+V */
+/*
+ * SAVE_KEYWORD("CtrlShiftCV"), but loading and saving is done by
+ * custom code, because the saved value is a string, and also sets
+ * CONF_ctrlshiftcv_custom
+ */
+CONF_OPTION(ctrlshiftcv, NONE, INT, 0, true, true, false, NULL, NULL)
+/* Custom clipboard name if CONF_mousepaste is set to CLIPUI_CUSTOM */
+/*
+ * Loading and saving is handled by custom code in conjunction
+ * with CONF_mousepaste
+ */
+CONF_OPTION(mousepaste_custom, NONE, STR, 0, true, true, false, NULL, NULL)
+/* Custom clipboard name if CONF_ctrlshiftins is set to CLIPUI_CUSTOM */
+/*
+ * Loading and saving is handled by custom code in conjunction
+ * with CONF_ctrlshiftins
+ */
+CONF_OPTION(ctrlshiftins_custom, NONE, STR, 0, true, true, false, NULL, NULL)
+/* Custom clipboard name if CONF_ctrlshiftcv is set to CLIPUI_CUSTOM */
+/*
+ * Loading and saving is handled by custom code in conjunction
+ * with CONF_ctrlshiftcv
+ */
+CONF_OPTION(ctrlshiftcv_custom, NONE, STR, 0, true, true, false, NULL, NULL)
+
+/* Character-set translation */
+CONF_OPTION(vtmode, NONE, INT, VT_UNICODE, false, false, false, "FontVTMode", &conf_enum_line_drawing)
+CONF_OPTION(line_codepage, NONE, STR, (int)"", false, false, false, "LineCodePage", NULL)
+CONF_OPTION(cjk_ambig_wide, NONE, BOOL, (int)false, false, false, false, "CJKAmbigWide", NULL)
+CONF_OPTION(utf8_override, NONE, BOOL, (int)true, false, false, false, "UTF8Override", NULL)
+CONF_OPTION(xlat_capslockcyr, NONE, BOOL, (int)false, false, false, false, "CapsLockCyr", NULL)
+
+/* X11 forwarding */
+CONF_OPTION(x11_forward, NONE, BOOL, (int)false, false, false, false, "X11Forward", NULL)
+CONF_OPTION(x11_display, NONE, STR, (int)"", false, false, false, "X11Display", NULL)
+CONF_OPTION(x11_auth, NONE, INT, X11_MIT, false, false, false, "X11AuthType", &conf_enum_x11_auth)
+CONF_OPTION(xauthfile, NONE, FILENAME, 0, false, false, false, "X11AuthFile", NULL)
+
+/* Port forwarding */
+/* accept conns from hosts other than localhost */
+CONF_OPTION(lport_acceptall, NONE, BOOL, (int)false, false, false, false, "LocalPortAcceptAll", NULL)
+/* same for remote forwarded ports */
+CONF_OPTION(rport_acceptall, NONE, BOOL, (int)false, false, false, false, "RemotePortAcceptAll", NULL)
+/*
+ * Subkeys for 'portfwd' can have the following forms:
+ *
+ *   [LR]localport
+ *   [LR]localaddr:localport
+ *
+ * Dynamic forwardings are indicated by an 'L' key, and the
+ * special value "D". For all other forwardings, the value should
+ * be of the form 'host:port'.
+ */
+/* necessary for mappings */
+CONF_OPTION(portfwd, STR, STR, 0, true, true, false, NULL, NULL)
+
+/* SSH bug compatibility modes. All FORCE_ON/FORCE_OFF/AUTO */
+CONF_OPTION(sshbug_ignore1, NONE, INT, AUTO, false, false, false, "BugIgnore1", &conf_enum_auto_off_on)
+CONF_OPTION(sshbug_plainpw1, NONE, INT, AUTO, false, false, false, "BugPlainPW1", &conf_enum_auto_off_on)
+CONF_OPTION(sshbug_rsa1, NONE, INT, AUTO, false, false, false, "BugRSA1", &conf_enum_auto_off_on)
+CONF_OPTION(sshbug_ignore2, NONE, INT, AUTO, false, false, false, "BugIgnore2", &conf_enum_auto_off_on)
+CONF_OPTION(sshbug_derivekey2, NONE, INT, AUTO, false, false, false, "BugDeriveKey2", &conf_enum_auto_off_on)
+CONF_OPTION(sshbug_rsapad2, NONE, INT, AUTO, false, false, false, "BugRSAPad2", &conf_enum_auto_off_on)
+CONF_OPTION(sshbug_pksessid2, NONE, INT, AUTO, false, false, false, "BugPKSessID2", &conf_enum_auto_off_on)
+CONF_OPTION(sshbug_rekey2, NONE, INT, AUTO, false, false, false, "BugRekey2", &conf_enum_auto_off_on)
+CONF_OPTION(sshbug_maxpkt2, NONE, INT, AUTO, false, false, false, "BugMaxPkt2", &conf_enum_auto_off_on)
+CONF_OPTION(sshbug_oldgex2, NONE, INT, AUTO, false, false, false, "BugOldGex2", &conf_enum_auto_off_on)
+CONF_OPTION(sshbug_winadj, NONE, INT, AUTO, false, false, false, "BugWinadj", &conf_enum_auto_off_on)
+CONF_OPTION(sshbug_chanreq, NONE, INT, AUTO, false, false, false, "BugChanReq", &conf_enum_auto_off_on)
+CONF_OPTION(sshbug_dropstart, NONE, INT, FORCE_OFF, false, false, false, "BugDropStart", &conf_enum_off1_on2)
+CONF_OPTION(sshbug_filter_kexinit, NONE, INT, FORCE_OFF, false, false, false, "BugFilterKexinit", &conf_enum_off1_on2)
+CONF_OPTION(sshbug_rsa_sha2_cert_userauth, NONE, INT, AUTO, false, false, false, "BugRSASHA2CertUserauth", &conf_enum_auto_off_on)
+/* there was an earlier keyword called "BuggyMAC" */
+CONF_OPTION(sshbug_hmac2, NONE, INT, AUTO, false, true, false, "BugHMAC2", &conf_enum_auto_off_on)
+
+/* Options for Unix. Should split out into platform-dependent part. */
+/* used by Unix pterm */
+CONF_OPTION(stamp_utmp, NONE, BOOL, (int)true, false, false, false, "StampUtmp", NULL)
+/* used by Unix pterm */
+CONF_OPTION(login_shell, NONE, BOOL, (int)true, false, false, false, "LoginShell", NULL)
+CONF_OPTION(scrollbar_on_left, NONE, BOOL, (int)false, false, false, false, "ScrollbarOnLeft", NULL)
+CONF_OPTION(shadowbold, NONE, BOOL, (int)false, false, false, false, "ShadowBold", NULL)
+CONF_OPTION(boldfont, NONE, FONT, 0, false, false, false, "BoldFont", NULL)
+CONF_OPTION(widefont, NONE, FONT, 0, false, false, false, "WideFont", NULL)
+CONF_OPTION(wideboldfont, NONE, FONT, 0, false, false, false, "WideBoldFont", NULL)
+/* in pixels */
+CONF_OPTION(shadowboldoffset, NONE, INT, 1, false, false, false, "ShadowBoldOffset", NULL)
+CONF_OPTION(crhaslf, NONE, BOOL, (int)false, false, false, false, "CRImpliesLF", NULL)
+CONF_OPTION(winclass, NONE, STR, (int)"", false, false, false, "WindowClass", NULL)
+
+/* WINSCP BEGIN */
+CONF_OPTION(connect_timeout, NONE, INT, 0, false, false, true, NULL, NULL)
+CONF_OPTION(sndbuf, NONE, INT, 0, false, false, true, NULL, NULL)
+CONF_OPTION(srcaddr, NONE, STR, (int)"", false, false, true, NULL, NULL)
+CONF_OPTION(force_remote_cmd2, NONE, BOOL, (int)false, false, false, true, NULL, NULL)
+CONF_OPTION(change_password, NONE, BOOL, (int)false, false, false, true, NULL, NULL)
+/* WINSCP END */

+ 20 - 0
source/putty/logging.c

@@ -34,6 +34,8 @@ static Filename *xlatlognam(const Filename *s,
  */
  */
 static void logwrite(LogContext *ctx, ptrlen data)
 static void logwrite(LogContext *ctx, ptrlen data)
 {
 {
+    assert(false); // WINSCP
+
     /*
     /*
      * In state L_CLOSED, we call logfopen, which will set the state
      * In state L_CLOSED, we call logfopen, which will set the state
      * to one of L_OPENING, L_OPEN or L_ERROR. Hence we process all of
      * to one of L_OPENING, L_OPEN or L_ERROR. Hence we process all of
@@ -64,6 +66,8 @@ static PRINTF_LIKE(2, 3) void logprintf(LogContext *ctx, const char *fmt, ...)
     va_list ap;
     va_list ap;
     char *data;
     char *data;
 
 
+    assert(false); // WINSCP
+
     va_start(ap, fmt);
     va_start(ap, fmt);
     data = dupvprintf(fmt, ap);
     data = dupvprintf(fmt, ap);
     va_end(ap);
     va_end(ap);
@@ -95,6 +99,8 @@ static void logfopen_callback(void *vctx, int mode)
     const char *fmode;
     const char *fmode;
     bool shout = false;
     bool shout = false;
 
 
+    assert(false); // WINSCP
+
     if (mode == 0) {
     if (mode == 0) {
         ctx->state = L_ERROR;          /* disable logging */
         ctx->state = L_ERROR;          /* disable logging */
     } else {
     } else {
@@ -160,6 +166,8 @@ void logfopen(LogContext *ctx)
     struct tm tm;
     struct tm tm;
     int mode;
     int mode;
 
 
+    assert(false); // WINSCP
+
     /* Prevent repeat calls */
     /* Prevent repeat calls */
     if (ctx->state != L_CLOSED)
     if (ctx->state != L_CLOSED)
         return;
         return;
@@ -207,6 +215,8 @@ void logfclose(LogContext *ctx)
  */
  */
 void logtraffic(LogContext *ctx, unsigned char c, int logmode)
 void logtraffic(LogContext *ctx, unsigned char c, int logmode)
 {
 {
+    assert(false); // WINSCP
+
     if (ctx->logtype > 0) {
     if (ctx->logtype > 0) {
         if (ctx->logtype == logmode)
         if (ctx->logtype == logmode)
             logwrite(ctx, make_ptrlen(&c, 1));
             logwrite(ctx, make_ptrlen(&c, 1));
@@ -273,6 +283,8 @@ void log_packet(LogContext *ctx, int direction, int type,
           (ctx->logtype == LGTYP_PACKETS && texttype)))
           (ctx->logtype == LGTYP_PACKETS && texttype)))
         return;
         return;
 
 
+    assert(false); // WINSCP
+
     /* Packet header. */
     /* Packet header. */
     if (texttype) {
     if (texttype) {
         logprintf(ctx, "%s packet ",
         logprintf(ctx, "%s packet ",
@@ -408,10 +420,14 @@ void log_free(LogContext *ctx)
     sfree(ctx);
     sfree(ctx);
 }
 }
 
 
+#ifndef WINSCP
+
 void log_reconfig(LogContext *ctx, Conf *conf)
 void log_reconfig(LogContext *ctx, Conf *conf)
 {
 {
     bool reset_logging;
     bool reset_logging;
 
 
+    assert(false); // WINSCP
+
     if (!filename_equal(conf_get_filename(ctx->conf, CONF_logfilename),
     if (!filename_equal(conf_get_filename(ctx->conf, CONF_logfilename),
                         conf_get_filename(conf, CONF_logfilename)) ||
                         conf_get_filename(conf, CONF_logfilename)) ||
         conf_get_int(ctx->conf, CONF_logtype) !=
         conf_get_int(ctx->conf, CONF_logtype) !=
@@ -432,6 +448,8 @@ void log_reconfig(LogContext *ctx, Conf *conf)
         logfopen(ctx);
         logfopen(ctx);
 }
 }
 
 
+#endif
+
 /*
 /*
  * translate format codes into time/date strings
  * translate format codes into time/date strings
  * and insert them into log file name
  * and insert them into log file name
@@ -449,6 +467,8 @@ static Filename *xlatlognam(const Filename *src,
     const char *s;
     const char *s;
     Filename *ret;
     Filename *ret;
 
 
+    assert(false); // WINSCP
+
     buffer = strbuf_new();
     buffer = strbuf_new();
     s = filename_to_str(src);
     s = filename_to_str(src);
 
 

+ 5 - 0
source/putty/proxy/proxy.c

@@ -432,6 +432,11 @@ static SocketEndpointInfo *sk_proxy_endpoint_info(Socket *s, bool peer)
     if (peer)
     if (peer)
         return NULL;
         return NULL;
 
 
+    #ifdef WINSCP
+    // if proxy is connected synchronously, we get here from sk_new even before ps->sub_socket is assigned
+    if (ps->sub_socket == NULL) return NULL;
+    #endif
+
     /* But we can at least tell where we're coming _from_. */
     /* But we can at least tell where we're coming _from_. */
     return sk_endpoint_info(ps->sub_socket, false);
     return sk_endpoint_info(ps->sub_socket, false);
 }
 }

+ 4 - 1
source/putty/putty.h

@@ -1871,8 +1871,10 @@ struct ConfKeyInfo {
     int value_type;
     int value_type;
 
 
     union {
     union {
-        bool bval;
+        // WINSCP changed order, because only the first member can be initialized
+        // and char* can be casted to int, but not to bool
         int ival;
         int ival;
+        bool bval;
         const char *sval;
         const char *sval;
     } default_value;
     } default_value;
 
 
@@ -2592,6 +2594,7 @@ enum {
  * as fontspec_serialise and fontspec_deserialise above.
  * as fontspec_serialise and fontspec_deserialise above.
  */
  */
 Filename *filename_from_str(const char *string);
 Filename *filename_from_str(const char *string);
+Filename *filename_from_utf8(const char *ustr); // WINSCP
 const char *filename_to_str(const Filename *fn);
 const char *filename_to_str(const Filename *fn);
 const char* in_memory_key_data(const Filename *fn); // WINSCP
 const char* in_memory_key_data(const Filename *fn); // WINSCP
 bool filename_equal(const Filename *f1, const Filename *f2);
 bool filename_equal(const Filename *f1, const Filename *f2);

+ 38 - 3
source/putty/settings.c

@@ -450,7 +450,8 @@ static void wprefs(settings_w *sesskey, const char *name,
 {
 {
     strbuf *sb = strbuf_new();
     strbuf *sb = strbuf_new();
 
 
-    for (int i = 0; i < nvals; i++) {
+    int i; // WINSCP
+    for (i = 0; i < nvals; i++) {
         const char *s = val2key(mapping, nvals,
         const char *s = val2key(mapping, nvals,
                                 conf_get_int_int(conf, primary, i));
                                 conf_get_int_int(conf, primary, i));
         if (s)
         if (s)
@@ -538,7 +539,8 @@ void save_open_settings(settings_w *sesskey, Conf *conf)
     const char *p;
     const char *p;
 
 
     /* Save the settings simple enough to handle automatically */
     /* Save the settings simple enough to handle automatically */
-    for (size_t key = 0; key < N_CONFIG_OPTIONS; key++) {
+    size_t key; // WINSCP
+    for (key = 0; key < N_CONFIG_OPTIONS; key++) {
         const ConfKeyInfo *info = &conf_key_info[key];
         const ConfKeyInfo *info = &conf_key_info[key];
         if (!info->save_custom && !info->not_saved) {
         if (!info->save_custom && !info->not_saved) {
             /* Mappings are handled individually below */
             /* Mappings are handled individually below */
@@ -561,6 +563,7 @@ void save_open_settings(settings_w *sesskey, Conf *conf)
                     cp_to = CP_UTF8;
                     cp_to = CP_UTF8;
                 }
                 }
 
 
+                { // WINSCP
                 size_t wlen;
                 size_t wlen;
                 wchar_t *wide = dup_mb_to_wc_c(
                 wchar_t *wide = dup_mb_to_wc_c(
                     cp_from, orig, strlen(orig), &wlen);
                     cp_from, orig, strlen(orig), &wlen);
@@ -582,6 +585,7 @@ void save_open_settings(settings_w *sesskey, Conf *conf)
 
 
                 burnwcs(wide);
                 burnwcs(wide);
                 burnstr(converted);
                 burnstr(converted);
+                } // WINSCP
                 break;
                 break;
               }
               }
               case CONF_TYPE_INT: {
               case CONF_TYPE_INT: {
@@ -710,8 +714,36 @@ void load_open_settings(settings_r *sesskey, Conf *conf)
     int i;
     int i;
     char *prot;
     char *prot;
 
 
+    // WINSCP BEGIN Testing that our conf.winscp.h projection is valid
+    assert(conf_key_info[CONF_host].subkey_type == CONF_TYPE_NONE);
+    assert(conf_key_info[CONF_host].value_type == CONF_TYPE_STR);
+    assert(strcmp(conf_key_info[CONF_host].default_value.sval, "") == 0);
+    assert(!conf_key_info[CONF_host].save_custom);
+    assert(!conf_key_info[CONF_host].load_custom);
+    assert(!conf_key_info[CONF_host].not_saved);
+    assert(strcmp(conf_key_info[CONF_host].save_keyword, "HostName") == 0);
+    assert(conf_key_info[CONF_host].storage_enum == NULL);
+
+    assert(conf_key_info[CONF_close_on_exit].default_value.ival == AUTO);
+
+    assert(conf_key_info[CONF_proxy_type].storage_enum == &conf_enum_proxy_type);
+
+    assert(conf_key_info[CONF_remote_cmd2].not_saved);
+
+    assert(strcmp(conf_key_info[CONF_proxy_host].default_value.sval, "proxy") == 0);
+
+    assert(conf_key_info[CONF_ssh_kexlist].subkey_type == CONF_TYPE_INT);
+    assert(conf_key_info[CONF_ssh_kexlist].save_custom);
+    assert(conf_key_info[CONF_ssh_kexlist].load_custom);
+    assert(conf_key_info[CONF_ssh_kexlist].save_keyword == NULL);
+
+    assert(conf_key_info[CONF_ssh_prefer_known_hostkeys].default_value.bval == true);
+    // WINSCP END
+
+    { // WINSCP
     /* Load the settings simple enough to handle automatically */
     /* Load the settings simple enough to handle automatically */
-    for (size_t key = 0; key < N_CONFIG_OPTIONS; key++) {
+    size_t key; // WINSCP
+    for (key = 0; key < N_CONFIG_OPTIONS; key++) {
         const ConfKeyInfo *info = &conf_key_info[key];
         const ConfKeyInfo *info = &conf_key_info[key];
         if (info->not_saved) {
         if (info->not_saved) {
             /* Mappings are assumed to default to empty */
             /* Mappings are assumed to default to empty */
@@ -760,6 +792,7 @@ void load_open_settings(settings_r *sesskey, Conf *conf)
                     assert(success && "unmapped default");
                     assert(success && "unmapped default");
 
 
                     /* Now retrieve the stored value */
                     /* Now retrieve the stored value */
+                    { // WINSCP
                     int storageval = gppi_raw(sesskey, info->save_keyword,
                     int storageval = gppi_raw(sesskey, info->save_keyword,
                                               defstorage);
                                               defstorage);
 
 
@@ -770,6 +803,7 @@ void load_open_settings(settings_r *sesskey, Conf *conf)
                             info->storage_enum, storageval, &confval))
                             info->storage_enum, storageval, &confval))
                         confval = info->default_value.ival;
                         confval = info->default_value.ival;
                     conf_set_int(conf, key, confval);
                     conf_set_int(conf, key, confval);
+                    } // WINSCP
                 }
                 }
                 break;
                 break;
               case CONF_TYPE_BOOL:
               case CONF_TYPE_BOOL:
@@ -1049,6 +1083,7 @@ void load_open_settings(settings_r *sesskey, Conf *conf)
         }
         }
     }
     }
     gppmap(sesskey, "SSHManualHostKeys", conf, CONF_ssh_manual_hostkeys);
     gppmap(sesskey, "SSHManualHostKeys", conf, CONF_ssh_manual_hostkeys);
+    } // WINSCP
 }
 }
 
 
 bool do_defaults(const char *session, Conf *conf)
 bool do_defaults(const char *session, Conf *conf)

+ 5 - 5
source/putty/ssh/userauth2-client.c

@@ -539,7 +539,7 @@ static void ssh2_userauth_process_queue(PacketProtocolLayer *ppl)
         char *algname = NULL;
         char *algname = NULL;
         char *comment = NULL;
         char *comment = NULL;
 
 
-        ppl_logevent("Reading certificate file \"%s\"",
+        ppl_logevent(WINSCP_BOM "Reading certificate file \"%s\"",
                      filename_to_str(s->detached_cert_file));
                      filename_to_str(s->detached_cert_file));
         { // WINSCP
         { // WINSCP
         int keytype = key_type(s->detached_cert_file);
         int keytype = key_type(s->detached_cert_file);
@@ -586,7 +586,7 @@ static void ssh2_userauth_process_queue(PacketProtocolLayer *ppl)
             ppl_logevent("Unable to use this certificate file (%s)",
             ppl_logevent("Unable to use this certificate file (%s)",
                          cert_error);
                          cert_error);
             ppl_printf(
             ppl_printf(
-                "Unable to use certificate file \"%s\" (%s)\r\n",
+                WINSCP_BOM "Unable to use certificate file \"%s\" (%s)\r\n",
                 filename_to_str(s->detached_cert_file), cert_error);
                 filename_to_str(s->detached_cert_file), cert_error);
             sfree(cert_error);
             sfree(cert_error);
         }
         }
@@ -2476,7 +2476,7 @@ static void ssh2_userauth_add_alg_and_publickey(
          * SHA-512 name rsa-sha2-512-cert-v01@... .)
          * SHA-512 name rsa-sha2-512-cert-v01@... .)
          */
          */
         if (verbose) {
         if (verbose) {
-            ppl_logevent("Sending public key with certificate from \"%s\"",
+            ppl_logevent(WINSCP_BOM "Sending public key with certificate from \"%s\"",
                          filename_to_str(s->detached_cert_file));
                          filename_to_str(s->detached_cert_file));
         }
         }
         {
         {
@@ -2511,7 +2511,7 @@ static void ssh2_userauth_add_alg_and_publickey(
          * avoid verbosely logging once for the offer and once for the
          * avoid verbosely logging once for the offer and once for the
          * real auth attempt.) */
          * real auth attempt.) */
 	if (verbose) {
 	if (verbose) {
-            ppl_logevent("Not substituting certificate \"%s\" for public "
+            ppl_logevent(WINSCP_BOM "Not substituting certificate \"%s\" for public "
                          "key: %s", filename_to_str(s->detached_cert_file),
                          "key: %s", filename_to_str(s->detached_cert_file),
                          fail_reason->s);
                          fail_reason->s);
             if (s->publickey_blob) {
             if (s->publickey_blob) {
@@ -2521,7 +2521,7 @@ static void ssh2_userauth_add_alg_and_publickey(
                  * send the certificate, so we should make a loud error
                  * send the certificate, so we should make a loud error
                  * message about it as well as just commenting in the
                  * message about it as well as just commenting in the
                  * Event Log. */
                  * Event Log. */
-                ppl_printf("Unable to use certificate \"%s\" with public "
+                ppl_printf(WINSCP_BOM "Unable to use certificate \"%s\" with public "
                            "key \"%s\": %s\r\n",
                            "key \"%s\": %s\r\n",
                            filename_to_str(s->detached_cert_file),
                            filename_to_str(s->detached_cert_file),
                            filename_to_str(s->keyfile),
                            filename_to_str(s->keyfile),

+ 4 - 0
source/putty/utils/conf.c

@@ -475,12 +475,14 @@ bool conf_try_set_str(Conf *conf, int primary, const char *value)
     assert(conf_key_info[primary].value_type == CONF_TYPE_STR ||
     assert(conf_key_info[primary].value_type == CONF_TYPE_STR ||
            conf_key_info[primary].value_type == CONF_TYPE_STR_AMBI);
            conf_key_info[primary].value_type == CONF_TYPE_STR_AMBI);
 
 
+    { // WINSCP
     struct conf_entry *entry = snew(struct conf_entry);
     struct conf_entry *entry = snew(struct conf_entry);
     entry->key.primary = primary;
     entry->key.primary = primary;
     entry->value.u.stringval.str = dupstr(value);
     entry->value.u.stringval.str = dupstr(value);
     entry->value.u.stringval.utf8 = false;
     entry->value.u.stringval.utf8 = false;
     conf_insert(conf, entry);
     conf_insert(conf, entry);
     return true;
     return true;
+    } // WINSCP
 }
 }
 
 
 void conf_set_str(Conf *conf, int primary, const char *value)
 void conf_set_str(Conf *conf, int primary, const char *value)
@@ -497,12 +499,14 @@ bool conf_try_set_utf8(Conf *conf, int primary, const char *value)
     assert(conf_key_info[primary].value_type == CONF_TYPE_UTF8 ||
     assert(conf_key_info[primary].value_type == CONF_TYPE_UTF8 ||
            conf_key_info[primary].value_type == CONF_TYPE_STR_AMBI);
            conf_key_info[primary].value_type == CONF_TYPE_STR_AMBI);
 
 
+    { // WINSCP
     struct conf_entry *entry = snew(struct conf_entry);
     struct conf_entry *entry = snew(struct conf_entry);
     entry->key.primary = primary;
     entry->key.primary = primary;
     entry->value.u.stringval.str = dupstr(value);
     entry->value.u.stringval.str = dupstr(value);
     entry->value.u.stringval.utf8 = true;
     entry->value.u.stringval.utf8 = true;
     conf_insert(conf, entry);
     conf_insert(conf, entry);
     return true;
     return true;
+    } // WINSCP
 }
 }
 
 
 void conf_set_utf8(Conf *conf, int primary, const char *value)
 void conf_set_utf8(Conf *conf, int primary, const char *value)

+ 9 - 16
source/putty/utils/conf_data.c

@@ -4,8 +4,8 @@
     static const ConfSaveEnumValue conf_enum_values_##name[] = {        \
     static const ConfSaveEnumValue conf_enum_values_##name[] = {        \
         __VA_ARGS__                                                     \
         __VA_ARGS__                                                     \
     }; const ConfSaveEnumType conf_enum_##name = {                      \
     }; const ConfSaveEnumType conf_enum_##name = {                      \
-        .values = conf_enum_values_##name,                              \
-        .nvalues = lenof(conf_enum_values_##name),                      \
+        /*.values =*/ conf_enum_values_##name,                              \
+        /*.nvalues =*/ lenof(conf_enum_values_##name),                      \
     };
     };
 
 
 #define VALUE(eval, sval) { eval, sval, false }
 #define VALUE(eval, sval) { eval, sval, false }
@@ -16,7 +16,8 @@
 bool conf_enum_map_to_storage(const ConfSaveEnumType *etype,
 bool conf_enum_map_to_storage(const ConfSaveEnumType *etype,
                               int confval, int *storageval_out)
                               int confval, int *storageval_out)
 {
 {
-    for (size_t i = 0; i < etype->nvalues; i++)
+    size_t i; // WINSCP
+    for (i = 0; i < etype->nvalues; i++)
         if (!etype->values[i].obsolete &&
         if (!etype->values[i].obsolete &&
             etype->values[i].confval == confval) {
             etype->values[i].confval == confval) {
             *storageval_out = etype->values[i].storageval;
             *storageval_out = etype->values[i].storageval;
@@ -28,7 +29,8 @@ bool conf_enum_map_to_storage(const ConfSaveEnumType *etype,
 bool conf_enum_map_from_storage(const ConfSaveEnumType *etype,
 bool conf_enum_map_from_storage(const ConfSaveEnumType *etype,
                                 int storageval, int *confval_out)
                                 int storageval, int *confval_out)
 {
 {
-    for (size_t i = 0; i < etype->nvalues; i++)
+    size_t i; // WINSCP
+    for (i = 0; i < etype->nvalues; i++)
         if (etype->values[i].storageval == storageval) {
         if (etype->values[i].storageval == storageval) {
             *confval_out = etype->values[i].confval;
             *confval_out = etype->values[i].confval;
             return true;
             return true;
@@ -36,18 +38,9 @@ bool conf_enum_map_from_storage(const ConfSaveEnumType *etype,
     return false;
     return false;
 }
 }
 
 
-#define CONF_OPTION(id, ...) { __VA_ARGS__ },
-#define VALUE_TYPE(x) .value_type = CONF_TYPE_ ## x
-#define SUBKEY_TYPE(x) .subkey_type = CONF_TYPE_ ## x
-#define DEFAULT_INT(x) .default_value.ival = x
-#define DEFAULT_STR(x) .default_value.sval = x
-#define DEFAULT_BOOL(x) .default_value.bval = x
-#define SAVE_KEYWORD(x) .save_keyword = x
-#define STORAGE_ENUM(x) .storage_enum = &conf_enum_ ## x
-#define SAVE_CUSTOM .save_custom = true
-#define LOAD_CUSTOM .load_custom = true
-#define NOT_SAVED .not_saved = true
+#define CONF_OPTION(id, subkey_type, value_type, ...) \
+    { CONF_TYPE_ ## subkey_type, CONF_TYPE_ ## value_type, __VA_ARGS__ },
 
 
 const ConfKeyInfo conf_key_info[] = {
 const ConfKeyInfo conf_key_info[] = {
-    #include "conf.h"
+    #include "conf.winscp.h"
 };
 };

+ 6 - 0
source/putty/utils/decode_utf8.c

@@ -13,6 +13,7 @@ unsigned decode_utf8(BinarySource *src, DecodeUTF8Failure *err)
 
 
     /* If the source has no byte available, this will return 0, which
     /* If the source has no byte available, this will return 0, which
      * we'll return immediately and is a reasonable error return anyway */
      * we'll return immediately and is a reasonable error return anyway */
+    { // WINSCP
     unsigned char c = get_byte(src);
     unsigned char c = get_byte(src);
 
 
     /* One-byte cases. */
     /* One-byte cases. */
@@ -24,6 +25,7 @@ unsigned decode_utf8(BinarySource *src, DecodeUTF8Failure *err)
         return 0xFFFD;
         return 0xFFFD;
     }
     }
 
 
+    { // WINSCP
     unsigned long wc, min;
     unsigned long wc, min;
     size_t ncont;
     size_t ncont;
     if (c < 0xE0) {
     if (c < 0xE0) {
@@ -46,6 +48,7 @@ unsigned decode_utf8(BinarySource *src, DecodeUTF8Failure *err)
             *err = DUTF8_E_OUT_OF_DATA;
             *err = DUTF8_E_OUT_OF_DATA;
             return 0xFFFD;
             return 0xFFFD;
         }
         }
+        { // WINSCP
         unsigned char cont = get_byte(src);
         unsigned char cont = get_byte(src);
         if (!(0x80 <= cont && cont < 0xC0)) {
         if (!(0x80 <= cont && cont < 0xC0)) {
             BinarySource_REWIND_TO(src, src->pos - 1);
             BinarySource_REWIND_TO(src, src->pos - 1);
@@ -54,6 +57,7 @@ unsigned decode_utf8(BinarySource *src, DecodeUTF8Failure *err)
         }
         }
 
 
         wc = (wc << 6) | (cont & 0x3F);
         wc = (wc << 6) | (cont & 0x3F);
+        } // WINSCP
     }
     }
 
 
     if (wc < min) {
     if (wc < min) {
@@ -70,6 +74,8 @@ unsigned decode_utf8(BinarySource *src, DecodeUTF8Failure *err)
     }
     }
     *err = DUTF8_SUCCESS;
     *err = DUTF8_SUCCESS;
     return wc;
     return wc;
+    } // WINSCP
+    } // WINSCP
 }
 }
 
 
 const char *const decode_utf8_error_strings[DUTF8_N_FAILURE_CODES] = {
 const char *const decode_utf8_error_strings[DUTF8_N_FAILURE_CODES] = {

+ 2 - 0
source/putty/utils/decode_utf8_to_wide_string.c

@@ -23,8 +23,10 @@ wchar_t *decode_utf8_to_wide_string(const char *s)
         /* We ignore 'err': if it is set, then the character decode
         /* We ignore 'err': if it is set, then the character decode
          * function will have emitted U+FFFD REPLACEMENT CHARACTER,
          * function will have emitted U+FFFD REPLACEMENT CHARACTER,
          * which is what we'd have done in response anyway. */
          * which is what we'd have done in response anyway. */
+        { // WINSCP
         DecodeUTF8Failure err;
         DecodeUTF8Failure err;
         wlen += decode_utf8_to_wchar(src, ws + wlen, &err);
         wlen += decode_utf8_to_wchar(src, ws + wlen, &err);
+        } // WINSCP
     }
     }
 
 
     /* Reallocate to the final size and append the trailing NUL */
     /* Reallocate to the final size and append the trailing NUL */

+ 8 - 0
source/putty/windows/gss.c

@@ -138,6 +138,8 @@ struct ssh_gss_liblist *ssh_gss_setup(Conf *conf, LogContext *logctx) // MPEXT
 
 
     /* MIT Kerberos GSSAPI implementation */
     /* MIT Kerberos GSSAPI implementation */
     module = NULL;
     module = NULL;
+    putty_registry_pass(true);
+    { // WINSCP
     HKEY regkey = open_regkey_ro(HKEY_LOCAL_MACHINE,
     HKEY regkey = open_regkey_ro(HKEY_LOCAL_MACHINE,
                                  "SOFTWARE\\MIT\\Kerberos");
                                  "SOFTWARE\\MIT\\Kerberos");
     if (regkey) {
     if (regkey) {
@@ -152,6 +154,7 @@ struct ssh_gss_liblist *ssh_gss_setup(Conf *conf, LogContext *logctx) // MPEXT
                 sfree(dllPath);
                 sfree(dllPath);
             }
             }
 
 
+            { // WINSCP
             char *dllfile = dupcat(bindir, "\\gssapi"MIT_KERB_SUFFIX".dll");
             char *dllfile = dupcat(bindir, "\\gssapi"MIT_KERB_SUFFIX".dll");
             module = LoadLibraryEx(dllfile, NULL,
             module = LoadLibraryEx(dllfile, NULL,
                                    LOAD_LIBRARY_SEARCH_SYSTEM32 |
                                    LOAD_LIBRARY_SEARCH_SYSTEM32 |
@@ -177,9 +180,11 @@ struct ssh_gss_liblist *ssh_gss_setup(Conf *conf, LogContext *logctx) // MPEXT
             sfree(dllfile);
             sfree(dllfile);
             sfree(bindir);
             sfree(bindir);
             sfree(installdir);
             sfree(installdir);
+            } // WINSCP
         }
         }
         close_regkey(regkey);
         close_regkey(regkey);
     }
     }
+    putty_registry_pass(false);
     if (module) {
     if (module) {
         struct ssh_gss_library *lib =
         struct ssh_gss_library *lib =
             &list->libraries[list->nlibraries++];
             &list->libraries[list->nlibraries++];
@@ -235,6 +240,7 @@ struct ssh_gss_liblist *ssh_gss_setup(Conf *conf, LogContext *logctx) // MPEXT
      * Custom GSSAPI DLL.
      * Custom GSSAPI DLL.
      */
      */
     module = NULL;
     module = NULL;
+    { // WINSCP
     Filename *customlib = conf_get_filename(conf, CONF_ssh_gss_custom);
     Filename *customlib = conf_get_filename(conf, CONF_ssh_gss_custom);
     if (!filename_is_null(customlib)) {
     if (!filename_is_null(customlib)) {
         const wchar_t *path = customlib->wpath;
         const wchar_t *path = customlib->wpath;
@@ -303,6 +309,8 @@ struct ssh_gss_liblist *ssh_gss_setup(Conf *conf, LogContext *logctx) // MPEXT
 
 
 
 
     return list;
     return list;
+    } // WINSCP
+    } // WINSCP
 }
 }
 
 
 void ssh_gss_cleanup(struct ssh_gss_liblist *list)
 void ssh_gss_cleanup(struct ssh_gss_liblist *list)

+ 1 - 1
source/putty/windows/network.c

@@ -1222,7 +1222,7 @@ Socket *sk_new(SockAddr *addr, int port, bool privport, bool oobinline,
     err = 0;
     err = 0;
     do {
     do {
 #ifdef MPEXT
 #ifdef MPEXT
-        ret->error = NULL;
+        s->error = NULL;
 #endif
 #endif
         err = try_connect(s
         err = try_connect(s
 #ifdef MPEXT
 #ifdef MPEXT

+ 1 - 0
source/putty/windows/platform.h

@@ -828,6 +828,7 @@ HKEY open_regkey_fn_winscp(bool create, bool write, HKEY base, const char *path,
     reg_override_winscp() ? open_regkey_fn_winscp(true, true, base, __VA_ARGS__, (const char *)NULL) : open_regkey_fn(true, true, base, __VA_ARGS__, (const char *)NULL)
     reg_override_winscp() ? open_regkey_fn_winscp(true, true, base, __VA_ARGS__, (const char *)NULL) : open_regkey_fn(true, true, base, __VA_ARGS__, (const char *)NULL)
 void close_regkey(HKEY key);
 void close_regkey(HKEY key);
 void close_regkey_winscp(HKEY key);
 void close_regkey_winscp(HKEY key);
+void putty_registry_pass(bool enable);
 void del_regkey(HKEY key, const char *name);
 void del_regkey(HKEY key, const char *name);
 char *enum_regkey(HKEY key, int index);
 char *enum_regkey(HKEY key, int index);
 bool get_reg_dword(HKEY key, const char *name, DWORD *out);
 bool get_reg_dword(HKEY key, const char *name, DWORD *out);

+ 1 - 1
source/putty/windows/storage.c

@@ -185,7 +185,7 @@ Filename *read_setting_filename(settings_r *handle, const char *name)
 {
 {
     char *tmp = read_setting_s(handle, name);
     char *tmp = read_setting_s(handle, name);
     if (tmp) {
     if (tmp) {
-        Filename *ret = filename_from_str(tmp);
+        Filename *ret = filename_from_utf8(tmp); // WINSCP (though it might not have any effect for our uses of the code)
         sfree(tmp);
         sfree(tmp);
         return ret;
         return ret;
     } else
     } else

+ 38 - 8
source/putty/windows/unicode.c

@@ -22,6 +22,8 @@ static const WCHAR unitab_xterm_std[32] = {
     0x2502, 0x2264, 0x2265, 0x03c0, 0x2260, 0x00a3, 0x00b7, 0x0020
     0x2502, 0x2264, 0x2265, 0x03c0, 0x2260, 0x00a3, 0x00b7, 0x0020
 };
 };
 
 
+#endif
+
 /*
 /*
  * If the codepage is non-zero it's a window codepage, zero means use a
  * If the codepage is non-zero it's a window codepage, zero means use a
  * local codepage. The name is always converted to the first of any
  * local codepage. The name is always converted to the first of any
@@ -438,8 +440,12 @@ static const struct cp_list_item cp_list[] = {
     {0, 0}
     {0, 0}
 };
 };
 
 
+#ifndef WINSCP
+
 static void link_font(WCHAR *line_tbl, WCHAR *font_tbl, WCHAR attr);
 static void link_font(WCHAR *line_tbl, WCHAR *font_tbl, WCHAR attr);
 
 
+#endif
+
 /*
 /*
  * We keep a collection of reverse mappings from Unicode back to code pages,
  * We keep a collection of reverse mappings from Unicode back to code pages,
  * in the form of array[256] of array[256] of char. These live forever in a
  * in the form of array[256] of array[256] of char. These live forever in a
@@ -486,17 +492,21 @@ static reverse_mapping *make_reverse_mapping_inner(
     if (!reverse_mappings)
     if (!reverse_mappings)
         reverse_mappings = newtree234(reverse_mapping_cmp);
         reverse_mappings = newtree234(reverse_mapping_cmp);
 
 
+    { // WINSCP
     reverse_mapping *rmap = snew(reverse_mapping);
     reverse_mapping *rmap = snew(reverse_mapping);
     rmap->blocks = snewn(256, char *);
     rmap->blocks = snewn(256, char *);
     memset(rmap->blocks, 0, 256 * sizeof(char *));
     memset(rmap->blocks, 0, 256 * sizeof(char *));
 
 
-    for (size_t i = 0; i < 256; i++) {
+    { // WINSCP
+    size_t i; // WINSCP
+    for (i = 0; i < 256; i++) {
         /* These special kinds of value correspond to no Unicode character */
         /* These special kinds of value correspond to no Unicode character */
         if (DIRECT_CHAR(mapping[i]))
         if (DIRECT_CHAR(mapping[i]))
             continue;
             continue;
         if (DIRECT_FONT(mapping[i]))
         if (DIRECT_FONT(mapping[i]))
             continue;
             continue;
 
 
+        { // WINSCP
         size_t chr = mapping[i];
         size_t chr = mapping[i];
         size_t block = chr >> 8, index = chr & 0xFF;
         size_t block = chr >> 8, index = chr & 0xFF;
 
 
@@ -505,14 +515,21 @@ static reverse_mapping *make_reverse_mapping_inner(
             memset(rmap->blocks[block], 0, 256);
             memset(rmap->blocks[block], 0, 256);
         }
         }
         rmap->blocks[block][index] = i;
         rmap->blocks[block][index] = i;
+        } // WINSCP
     }
     }
 
 
     rmap->codepage = codepage;
     rmap->codepage = codepage;
+    { // WINSCP
     reverse_mapping *added = add234(reverse_mappings, rmap);
     reverse_mapping *added = add234(reverse_mappings, rmap);
     assert(added == rmap); /* we already checked it wasn't already in there */
     assert(added == rmap); /* we already checked it wasn't already in there */
     return added;
     return added;
+    } // WINSCP
+    } // WINSCP
+    } // WINSCP
 }
 }
 
 
+#ifndef WINSCP
+
 static void make_reverse_mapping(int codepage, const wchar_t *mapping)
 static void make_reverse_mapping(int codepage, const wchar_t *mapping)
 {
 {
     if (get_existing_reverse_mapping(codepage))
     if (get_existing_reverse_mapping(codepage))
@@ -520,6 +537,8 @@ static void make_reverse_mapping(int codepage, const wchar_t *mapping)
     make_reverse_mapping_inner(codepage, mapping);
     make_reverse_mapping_inner(codepage, mapping);
 }
 }
 
 
+#endif
+
 static reverse_mapping *get_reverse_mapping(int codepage)
 static reverse_mapping *get_reverse_mapping(int codepage)
 {
 {
     /*
     /*
@@ -536,15 +555,21 @@ static reverse_mapping *get_reverse_mapping(int codepage)
         return NULL;
         return NULL;
     if (codepage >= 65536 + lenof(cp_list))
     if (codepage >= 65536 + lenof(cp_list))
         return NULL;
         return NULL;
+    { // WINSCP
     const struct cp_list_item *cp = &cp_list[codepage - 65536];
     const struct cp_list_item *cp = &cp_list[codepage - 65536];
     if (!cp->cp_table)
     if (!cp->cp_table)
         return NULL;
         return NULL;
 
 
+    { // WINSCP
     wchar_t mapping[256];
     wchar_t mapping[256];
     get_unitab(codepage, mapping, 0);
     get_unitab(codepage, mapping, 0);
     return make_reverse_mapping_inner(codepage, mapping);
     return make_reverse_mapping_inner(codepage, mapping);
+    } // WINSCP
+    } // WINSCP
 }
 }
 
 
+#ifndef WINSCP
+
 void init_ucs(Conf *conf, struct unicode_data *ucsdata)
 void init_ucs(Conf *conf, struct unicode_data *ucsdata)
 {
 {
     int i;
     int i;
@@ -1210,6 +1235,8 @@ const char *cp_enumerate(int index)
     return cp_list[index].name;
     return cp_list[index].name;
 }
 }
 
 
+#endif
+
 void get_unitab(int codepage, wchar_t *unitab, int ftype)
 void get_unitab(int codepage, wchar_t *unitab, int ftype)
 {
 {
     char tbuf[4];
     char tbuf[4];
@@ -1254,6 +1281,7 @@ bool BinarySink_put_wc_to_mb(
     if (!wclen)
     if (!wclen)
         return true;
         return true;
 
 
+    { // WINSCP
     reverse_mapping *rmap = get_reverse_mapping(codepage);
     reverse_mapping *rmap = get_reverse_mapping(codepage);
 
 
     if (rmap) {
     if (rmap) {
@@ -1261,7 +1289,8 @@ bool BinarySink_put_wc_to_mb(
         bool defchr_len_known = false;
         bool defchr_len_known = false;
 
 
         /* Do this by array lookup if we can. */
         /* Do this by array lookup if we can. */
-        for (size_t i = 0; i < wclen; i++) {
+        size_t i; // WINSCP
+        for (i = 0; i < wclen; i++) {
             wchar_t ch = wcstr[i];
             wchar_t ch = wcstr[i];
             int by;
             int by;
             const char *blk;
             const char *blk;
@@ -1351,16 +1380,12 @@ bool BinarySink_put_wc_to_mb(
 
 
     /* No other fallbacks are available */
     /* No other fallbacks are available */
     return false;
     return false;
+    } // WINSCP
 }
 }
 
 
-#endif
-
 bool BinarySink_put_mb_to_wc(
 bool BinarySink_put_mb_to_wc(
     BinarySink *bs, int codepage, const char *mbstr, int mblen)
     BinarySink *bs, int codepage, const char *mbstr, int mblen)
 {
 {
-    #ifdef WINSCP
-    pinitassert(codepage == DEFAULT_CODEPAGE);
-    #else
     if (!mblen)
     if (!mblen)
         return true;
         return true;
 
 
@@ -1370,20 +1395,26 @@ bool BinarySink_put_mb_to_wc(
         size_t index = codepage - 65536;
         size_t index = codepage - 65536;
         if (index >= lenof(cp_list))
         if (index >= lenof(cp_list))
             return false;
             return false;
+        { // WINSCP
         const struct cp_list_item *cp = &cp_list[index];
         const struct cp_list_item *cp = &cp_list[index];
         if (!cp->cp_table)
         if (!cp->cp_table)
             return false;
             return false;
 
 
+        { // WINSCP
         unsigned tablebase = 256 - cp->cp_size;
         unsigned tablebase = 256 - cp->cp_size;
 
 
         while (mblen > 0) {
         while (mblen > 0) {
             mblen--;
             mblen--;
+            { // WINSCP
             unsigned c = 0xFF & *mbstr++;
             unsigned c = 0xFF & *mbstr++;
             wchar_t wc = (c < tablebase ? c : cp->cp_table[c - tablebase]);
             wchar_t wc = (c < tablebase ? c : cp->cp_table[c - tablebase]);
             put_data(bs, &wc, sizeof(wc));
             put_data(bs, &wc, sizeof(wc));
+            } // WINSCP
         }
         }
 
 
         return true;
         return true;
+        } // WINSCP
+        } // WINSCP
     }
     }
 
 
     {
     {
@@ -1411,7 +1442,6 @@ bool BinarySink_put_mb_to_wc(
                 currsize = allocsize;
                 currsize = allocsize;
             }
             }
         }
         }
-    #endif
 
 
         smemclr(allocbuf, allocsize * sizeof(wchar_t));
         smemclr(allocbuf, allocsize * sizeof(wchar_t));
         if (success)
         if (success)

+ 3 - 36
source/putty/windows/utils/filename.c

@@ -48,7 +48,7 @@ Filename *filename_copy(const Filename *fn)
 #ifdef WINSCP
 #ifdef WINSCP
 const char* in_memory_key_data(const Filename *fn)
 const char* in_memory_key_data(const Filename *fn)
 {
 {
-    const char* result = fn->path;
+    const char* result = fn->cpath;
     if (result[0] != '@')
     if (result[0] != '@')
     {
     {
         result = NULL;
         result = NULL;
@@ -84,7 +84,8 @@ const char *filename_to_str(const Filename *fn)
     #ifdef WINSCP
     #ifdef WINSCP
     if (in_memory_key_data(fn) != NULL) return "in-memory";
     if (in_memory_key_data(fn) != NULL) return "in-memory";
     #endif
     #endif
-    return fn->cpath;                  /* FIXME */
+    // WINSCP
+    return fn->utf8path;                  /* FIXME */
 }
 }
 
 
 bool filename_equal(const Filename *f1, const Filename *f2)
 bool filename_equal(const Filename *f1, const Filename *f2)
@@ -140,37 +141,3 @@ FILE *f_open(const Filename *fn, const char *mode, bool isprivate)
     sfree(wmode);
     sfree(wmode);
     return fp;
     return fp;
 }
 }
-
-#ifdef WINSCP
-
-FILE * mp_wfopen(const char *filename, const char *mode)
-{
-    size_t len = strlen(filename);
-    wchar_t * wfilename = snewn(len * 10, wchar_t);
-    size_t wlen = MultiByteToWideChar(CP_UTF8, 0, filename, -1, wfilename, len * 10);
-    FILE * file;
-    if (wlen <= 0)
-    {
-        file = NULL;
-    }
-    else
-    {
-        wchar_t wmode[3];
-        memset(wmode, 0, sizeof(wmode));
-        wmode[0] = (wchar_t)mode[0];
-        if (mode[0] != '\0')
-        {
-            wmode[1] = (wchar_t)mode[1];
-            if (mode[1] != '\0')
-            {
-                assert(mode[2] == '\0');
-            }
-        }
-
-        file = _wfopen(wfilename, wmode);
-    }
-    sfree(wfilename);
-    return file;
-}
-
-#endif