Martin Prikryl 16 years ago
parent
commit
e7d46b4863

+ 5 - 5
Console.rc

@@ -1,6 +1,6 @@
 1 VERSIONINFO
-FILEVERSION 2,3,0,111
-PRODUCTVERSION 2,3,0,111
+FILEVERSION 2,3,0,114
+PRODUCTVERSION 2,3,0,114
 FILEOS 0x4
 FILETYPE 0x1
 {
@@ -10,14 +10,14 @@ FILETYPE 0x1
         {
             VALUE "CompanyName", "Martin Prikryl\0"
             VALUE "FileDescription", "Console interface for WinSCP\0"
-            VALUE "FileVersion", "2.3.0.111\0"
+            VALUE "FileVersion", "2.3.0.114\0"
             VALUE "InternalName", "console\0"
             VALUE "LegalCopyright", "(c) 2000-2009 Martin Prikryl\0"
             VALUE "LegalTrademarks", "\0"
             VALUE "OriginalFilename", "winscp.com\0"
             VALUE "ProductName", "WinSCP\0"
-            VALUE "ProductVersion", "4.2.4.0\0"
-            VALUE "ReleaseType", "beta\0"
+            VALUE "ProductVersion", "4.2.5.0\0"
+            VALUE "ReleaseType", "stable\0"
             VALUE "WWW", "http://winscp.net/\0"
         }
     }

+ 5 - 5
DragExt.rc

@@ -1,6 +1,6 @@
 1 VERSIONINFO
-FILEVERSION 1,1,9,105
-PRODUCTVERSION 1,1,9,105
+FILEVERSION 1,1,9,108
+PRODUCTVERSION 1,1,9,108
 FILEOS 0x4
 FILETYPE 0x2
 {
@@ -10,14 +10,14 @@ FILETYPE 0x2
         {
             VALUE "CompanyName", "Martin Prikryl\0"
             VALUE "FileDescription", "Drag&Drop shell extension for WinSCP (32-bit)\0"
-            VALUE "FileVersion", "1.1.9.105\0"
+            VALUE "FileVersion", "1.1.9.108\0"
             VALUE "InternalName", "dragext32\0"
             VALUE "LegalCopyright", "(c) 2000-2009 Martin Prikryl\0"
             VALUE "LegalTrademarks", "\0"
             VALUE "OriginalFilename", "dragext.dll\0"
             VALUE "ProductName", "WinSCP\0"
-            VALUE "ProductVersion", "4.2.4.0\0"
-            VALUE "ReleaseType", "beta\0"
+            VALUE "ProductVersion", "4.2.5.0\0"
+            VALUE "ReleaseType", "stable\0"
             VALUE "WWW", "http://winscp.net/\0"
         }
     }

+ 5 - 5
DragExt64.rc

@@ -1,6 +1,6 @@
 1 VERSIONINFO
-FILEVERSION 1,1,9,105
-PRODUCTVERSION 1,1,9,105
+FILEVERSION 1,1,9,108
+PRODUCTVERSION 1,1,9,108
 FILEOS 0x4
 FILETYPE 0x2
 {
@@ -10,14 +10,14 @@ FILETYPE 0x2
         {
             VALUE "CompanyName", "Martin Prikryl\0"
             VALUE "FileDescription", "Drag&Drop shell extension for WinSCP (64-bit)\0"
-            VALUE "FileVersion", "1.1.9.105\0"
+            VALUE "FileVersion", "1.1.9.108\0"
             VALUE "InternalName", "dragext64\0"
             VALUE "LegalCopyright", "(c) 2000-2009 Martin Prikryl\0"
             VALUE "LegalTrademarks", "\0"
             VALUE "OriginalFilename", "dragext64.dll\0"
             VALUE "ProductName", "WinSCP\0"
-            VALUE "ProductVersion", "4.2.4.0\0"
-            VALUE "ReleaseType", "beta\0"
+            VALUE "ProductVersion", "4.2.5.0\0"
+            VALUE "ReleaseType", "stable\0"
             VALUE "WWW", "http://winscp.net/\0"
         }
     }

+ 2 - 0
WinSCP.cpp

@@ -17,6 +17,8 @@ WINAPI WinMain(HINSTANCE, HINSTANCE, LPSTR, int)
   try
   {
     Application->Initialize();
+    SetEnvironmentVariable("WINSCP_PATH",
+      ExcludeTrailingBackslash(ExtractFilePath(Application->ExeName)).c_str());
     CoreInitialize();
     InitializeWinHelp();
     InitializeSystemSettings();

+ 6 - 6
WinSCP.rc

@@ -1,6 +1,6 @@
 1 VERSIONINFO
-FILEVERSION 4,2,4,610
-PRODUCTVERSION 4,2,4,610
+FILEVERSION 4,2,5,624
+PRODUCTVERSION 4,2,5,624
 FILEOS 0x4
 FILETYPE 0x1
 {
@@ -10,14 +10,14 @@ FILETYPE 0x1
         {
             VALUE "CompanyName", "Martin Prikryl\0"
             VALUE "FileDescription", "WinSCP: SFTP, FTP and SCP client\0"
-            VALUE "FileVersion", "4.2.4.610\0"
+            VALUE "FileVersion", "4.2.5.624\0"
             VALUE "InternalName", "winscp\0"
             VALUE "LegalCopyright", "(c) 2000-2009 Martin Prikryl\0"
             VALUE "LegalTrademarks", "\0"
-            VALUE "OriginalFilename", "winscp424.exe\0"
+            VALUE "OriginalFilename", "winscp425.exe\0"
             VALUE "ProductName", "WinSCP\0"
-            VALUE "ProductVersion", "4.2.4.0\0"
-            VALUE "ReleaseType", "beta\0"
+            VALUE "ProductVersion", "4.2.5.0\0"
+            VALUE "ReleaseType", "stable\0"
             VALUE "WWW", "http://winscp.net/\0"
         }
     }

+ 39 - 11
core/Common.cpp

@@ -443,7 +443,7 @@ bool __fastcall CompareFileName(const AnsiString & Path1, const AnsiString & Pat
   }
   else
   {
-    Result = AnsiSameText(ExtractShortPathName(Path1), ExtractShortPathName(Path2));
+    Result = AnsiSameText(ShortPath1, ShortPath2);
   }
   return Result;
 }
@@ -664,6 +664,30 @@ void __fastcall ProcessLocalDirectory(AnsiString DirName,
   }
 }
 //---------------------------------------------------------------------------
+TDateTime __fastcall EncodeDateVerbose(Word Year, Word Month, Word Day)
+{
+  try
+  {
+    return EncodeDate(Year, Month, Day);
+  }
+  catch (EConvertError & E)
+  {
+    throw EConvertError(FORMAT("%s [%d-%d-%d]", (E.Message, int(Year), int(Month), int(Day))));
+  }
+}
+//---------------------------------------------------------------------------
+TDateTime __fastcall EncodeTimeVerbose(Word Hour, Word Min, Word Sec, Word MSec)
+{
+  try
+  {
+    return EncodeTime(Hour, Min, Sec, MSec);
+  }
+  catch (EConvertError & E)
+  {
+    throw EConvertError(FORMAT("%s [%d:%d:%d.%d]", (E.Message, int(Hour), int(Min), int(Sec), int(MSec))));
+  }
+}
+//---------------------------------------------------------------------------
 struct TDateTimeParams
 {
   TDateTime UnixEpoch;
@@ -698,7 +722,6 @@ static TDateTimeParams * __fastcall GetDateTimeParams()
       switch (GTZI)
       {
         case TIME_ZONE_ID_UNKNOWN:
-          DateTimeParams.CurrentDifferenceSec = 0;
           DateTimeParams.CurrentDaylightDifferenceSec = 0;
           break;
 
@@ -715,7 +738,7 @@ static TDateTimeParams * __fastcall GetDateTimeParams()
           throw Exception(TIMEZONE_ERROR);
       }
       // Is it same as SysUtils::UnixDateDelta = 25569 ??
-      DateTimeParams.UnixEpoch = EncodeDate(1970, 1, 1);
+      DateTimeParams.UnixEpoch = EncodeDateVerbose(1970, 1, 1);
 
       DateTimeParams.BaseDifferenceSec = TZI.Bias;
       DateTimeParams.BaseDifference = double(TZI.Bias) / 1440;
@@ -750,7 +773,7 @@ static void __fastcall EncodeDSTMargin(const SYSTEMTIME & Date, unsigned short Y
 {
   if (Date.wYear == 0)
   {
-    TDateTime Temp = EncodeDate(Year, Date.wMonth, 1);
+    TDateTime Temp = EncodeDateVerbose(Year, Date.wMonth, 1);
     Result = Temp + ((Date.wDayOfWeek - DayOfWeek(Temp) + 8) % 7) +
       (7 * (Date.wDay - 1));
     if (Date.wDay == 5)
@@ -762,18 +785,18 @@ static void __fastcall EncodeDSTMargin(const SYSTEMTIME & Date, unsigned short Y
         Year++;
       }
 
-      if (Result > EncodeDate(Year, Month, 1))
+      if (Result >= EncodeDateVerbose(Year, Month, 1))
       {
         Result -= 7;
       }
     }
-    Result += EncodeTime(Date.wHour, Date.wMinute, Date.wSecond,
+    Result += EncodeTimeVerbose(Date.wHour, Date.wMinute, Date.wSecond,
       Date.wMilliseconds);
   }
   else
   {
-    Result = EncodeDate(Year, Date.wMonth, Date.wDay) +
-      EncodeTime(Date.wHour, Date.wMinute, Date.wSecond, Date.wMilliseconds);
+    Result = EncodeDateVerbose(Year, Date.wMonth, Date.wDay) +
+      EncodeTimeVerbose(Date.wHour, Date.wMinute, Date.wSecond, Date.wMilliseconds);
   }
 }
 //---------------------------------------------------------------------------
@@ -793,7 +816,12 @@ static bool __fastcall IsDateInDST(const TDateTime & DateTime)
   TDateTimeParams * Params = GetDateTimeParams();
   bool Result;
 
-  if (Params->StandardDate.wMonth == 0)
+  // On some systems it occurs that StandardDate is unset, while
+  // DaylightDate is set. MSDN states that this is invalid and
+  // should be treated as if there is no daylinght saving.
+  // So check both.
+  if ((Params->StandardDate.wMonth == 0) ||
+      (Params->DaylightDate.wMonth == 0))
   {
     Result = false;
   }
@@ -1011,8 +1039,8 @@ void __fastcall UnifyDateTimePrecision(TDateTime & DateTime1, TDateTime & DateTi
     }
     if (Changed)
     {
-      DateTime1 = EncodeDate(Y1, M1, D1) + EncodeTime(H1, N1, S1, MS1);
-      DateTime2 = EncodeDate(Y2, M2, D2) + EncodeTime(H2, N2, S2, MS2);
+      DateTime1 = EncodeDateVerbose(Y1, M1, D1) + EncodeTimeVerbose(H1, N1, S1, MS1);
+      DateTime2 = EncodeDateVerbose(Y2, M2, D2) + EncodeTimeVerbose(H2, N2, S2, MS2);
     }
   }
 }

+ 2 - 0
core/Common.h

@@ -86,6 +86,8 @@ enum TDSTMode
   dstmUnix = 1, // adjust UTC time to Windows "bug"
   dstmKeep = 2
 };
+TDateTime __fastcall EncodeDateVerbose(Word Year, Word Month, Word Day);
+TDateTime __fastcall EncodeTimeVerbose(Word Hour, Word Min, Word Sec, Word MSec);
 TDateTime __fastcall UnixToDateTime(__int64 TimeStamp, TDSTMode DSTMode);
 FILETIME __fastcall DateTimeToFileTime(const TDateTime DateTime, TDSTMode DSTMode);
 TDateTime __fastcall AdjustDateTimeFromUnix(TDateTime DateTime, TDSTMode DSTMode);

+ 16 - 2
core/Configuration.cpp

@@ -530,12 +530,26 @@ void __fastcall TConfiguration::CleanupIniFile()
 //---------------------------------------------------------------------------
 AnsiString __fastcall TConfiguration::EncryptPassword(AnsiString Password, AnsiString Key)
 {
-  return ::EncryptPassword(Password, Key);
+  if (Password.IsEmpty())
+  {
+    return AnsiString();
+  }
+  else
+  {
+    return ::EncryptPassword(Password, Key);
+  }
 }
 //---------------------------------------------------------------------------
 AnsiString __fastcall TConfiguration::DecryptPassword(AnsiString Password, AnsiString Key)
 {
-  return ::DecryptPassword(Password, Key);
+  if (Password.IsEmpty())
+  {
+    return AnsiString();
+  }
+  else
+  {
+    return ::DecryptPassword(Password, Key);
+  }
 }
 //---------------------------------------------------------------------------
 AnsiString __fastcall TConfiguration::StronglyRecryptPassword(AnsiString Password, AnsiString /*Key*/)

+ 5 - 0
core/CopyParam.cpp

@@ -502,6 +502,11 @@ bool __fastcall TCopyParamType::AllowResume(__int64 Size) const
   }
 }
 //---------------------------------------------------------------------------
+bool __fastcall TCopyParamType::AllowAnyTransfer() const
+{
+  return ExcludeFileMask.Masks.IsEmpty();
+}
+//---------------------------------------------------------------------------
 bool __fastcall TCopyParamType::AllowTransfer(AnsiString FileName,
   TOperationSide Side, bool Directory, const TFileMasks::TParams & Params) const
 {

+ 1 - 0
core/CopyParam.h

@@ -78,6 +78,7 @@ public:
   bool __fastcall AllowResume(__int64 Size) const;
   AnsiString __fastcall ValidLocalFileName(AnsiString FileName) const;
   AnsiString __fastcall ValidLocalPath(AnsiString Path) const;
+  bool __fastcall AllowAnyTransfer() const;
   bool __fastcall AllowTransfer(AnsiString FileName, TOperationSide Side,
     bool Directory, const TFileMasks::TParams & Params) const;
 

+ 17 - 0
core/Exceptions.cpp

@@ -30,6 +30,23 @@ bool __fastcall ExceptionMessage(Exception * E, AnsiString & Message)
   return Result;
 }
 //---------------------------------------------------------------------------
+TStrings * ExceptionToMoreMessages(Exception * E)
+{
+  TStrings * Result = NULL;
+  AnsiString Message;
+  if (ExceptionMessage(E, Message))
+  {
+    Result = new TStringList();
+    Result->Add(Message);
+    ExtException * ExtE = dynamic_cast<ExtException *>(E);
+    if (ExtE != NULL)
+    {
+      Result->AddStrings(ExtE->MoreMessages);
+    }
+  }
+  return Result;
+}
+//---------------------------------------------------------------------------
 __fastcall ExtException::ExtException(Exception * E) :
   Exception("")
 {

+ 3 - 2
core/Exceptions.h

@@ -8,6 +8,9 @@
 #include <System.hpp>
 //---------------------------------------------------------------------------
 bool __fastcall ExceptionMessage(Exception * E, AnsiString & Message);
+AnsiString __fastcall LastSysErrorMessage();
+TStrings * ExceptionToMoreMessages(Exception * E);
+//---------------------------------------------------------------------------
 enum TOnceDoneOperation { odoIdle, odoDisconnect, odoShutDown };
 //---------------------------------------------------------------------------
 class ExtException : public Sysutils::Exception
@@ -96,6 +99,4 @@ public:
   TOnceDoneOperation Operation;
 };
 //---------------------------------------------------------------------------
-AnsiString __fastcall LastSysErrorMessage();
-//---------------------------------------------------------------------------
 #endif  // Exceptions

+ 6 - 2
core/FileInfo.cpp

@@ -24,11 +24,12 @@ unsigned int VERSION_GetFileVersionInfo_PE(const char * FileName, unsigned int D
 {
   unsigned int Len;
 
-
+  bool NeedFree = false;
   HMODULE Module = GetModuleHandle(FileName);
   if (Module == NULL)
   {
     Module = LoadLibraryEx(FileName, 0, LOAD_LIBRARY_AS_DATAFILE);
+    NeedFree = true;
   }
   if (Module == NULL)
   {
@@ -85,7 +86,10 @@ unsigned int VERSION_GetFileVersionInfo_PE(const char * FileName, unsigned int D
     }
     __finally
     {
-      FreeLibrary(Module);
+      if (NeedFree)
+      {
+        FreeLibrary(Module);
+      }
     }
   }
 

+ 22 - 21
core/FtpFileSystem.cpp

@@ -1295,26 +1295,22 @@ void __fastcall TFTPFileSystem::Source(const AnsiString FileName,
 
   OperationProgress->SetFile(FileName, false);
 
-  __int64 Size;
-  int Attrs;
-
-  FTerminal->OpenLocalFile(FileName, GENERIC_READ, &Attrs,
-    NULL, NULL, NULL, NULL, &Size);
-
-  bool Dir = FLAGSET(Attrs, faDirectory);
-
-  TFileMasks::TParams MaskParams;
-  MaskParams.Size = Size;
-
   if (FLAGCLEAR(Params, cpDelete) &&
-      !CopyParam->AllowTransfer(FileName, osLocal, Dir, MaskParams))
+      !FTerminal->AllowLocalFileTransfer(FileName, CopyParam))
   {
     FTerminal->LogEvent(FORMAT("File \"%s\" excluded from transfer", (FileName)));
     THROW_SKIP_FILE_NULL;
   }
 
+  __int64 Size;
+  int Attrs;
+
+  FTerminal->OpenLocalFile(FileName, GENERIC_READ, &Attrs,
+    NULL, NULL, NULL, NULL, &Size);
+
   OperationProgress->SetFileInProgress();
 
+  bool Dir = FLAGSET(Attrs, faDirectory);
   if (Dir)
   {
     DirectorySource(IncludeTrailingBackslash(FileName), TargetDir,
@@ -1336,6 +1332,8 @@ void __fastcall TFTPFileSystem::Source(const AnsiString FileName,
     OperationProgress->TransferingFile = false;
 
     // Will we use ASCII of BINARY file tranfer?
+    TFileMasks::TParams MaskParams;
+    MaskParams.Size = Size;
     OperationProgress->SetAsciiTransfer(
       CopyParam->UseAsciiTransfer(FileName, osLocal, MaskParams));
     FTerminal->LogEvent(
@@ -1389,9 +1387,12 @@ void __fastcall TFTPFileSystem::Source(const AnsiString FileName,
   /* TODO : Delete also read-only files. */
   if (FLAGSET(Params, cpDelete))
   {
-    FILE_OPERATION_LOOP (FMTLOAD(DELETE_LOCAL_FILE_ERROR, (FileName)),
-      THROWOSIFFALSE(Sysutils::DeleteFile(FileName));
-    )
+    if (!Dir)
+    {
+      FILE_OPERATION_LOOP (FMTLOAD(DELETE_LOCAL_FILE_ERROR, (FileName)),
+        THROWOSIFFALSE(Sysutils::DeleteFile(FileName));
+      )
+    }
   }
   else if (CopyParam->ClearArchive && FLAGSET(Attrs, faArchive))
   {
@@ -2747,13 +2748,13 @@ TDateTime __fastcall TFTPFileSystem::ConvertRemoteTimestamp(time_t Time, bool Ha
   if (Tm != NULL)
   {
     // should be the same as HandleListData
-    Result = EncodeDate(
+    Result = EncodeDateVerbose(
       static_cast<unsigned short>(Tm->tm_year + 1900),
       static_cast<unsigned short>(Tm->tm_mon + 1),
       static_cast<unsigned short>(Tm->tm_mday));
     if (HasTime)
     {
-      Result += EncodeTime(
+      Result += EncodeTimeVerbose(
         static_cast<unsigned short>(Tm->tm_hour),
         static_cast<unsigned short>(Tm->tm_min),
         static_cast<unsigned short>(Tm->tm_sec), 0);
@@ -2914,10 +2915,10 @@ AnsiString __fastcall FormatContact(const TFtpsCertificateData::TContact & Conta
 AnsiString __fastcall FormatValidityTime(const TFtpsCertificateData::TValidityTime & ValidityTime)
 {
   return FormatDateTime("ddddd tt",
-    EncodeDate(
+    EncodeDateVerbose(
       (unsigned short)ValidityTime.Year, (unsigned short)ValidityTime.Month,
       (unsigned short)ValidityTime.Day) +
-    EncodeTime(
+    EncodeTimeVerbose(
       (unsigned short)ValidityTime.Hour, (unsigned short)ValidityTime.Min,
       (unsigned short)ValidityTime.Sec, 0));
 }
@@ -3187,12 +3188,12 @@ bool __fastcall TFTPFileSystem::HandleListData(const char * Path,
         {
           // should be the same as ConvertRemoteTimestamp
           TDateTime Modification =
-            EncodeDate((unsigned short)Entry->Year, (unsigned short)Entry->Month,
+            EncodeDateVerbose((unsigned short)Entry->Year, (unsigned short)Entry->Month,
               (unsigned short)Entry->Day);
           if (Entry->HasTime)
           {
             File->Modification = Modification +
-              EncodeTime((unsigned short)Entry->Hour, (unsigned short)Entry->Minute, 0, 0);
+              EncodeTimeVerbose((unsigned short)Entry->Hour, (unsigned short)Entry->Minute, 0, 0);
             // not exact as we got year as well, but it is most probably
             // guessed by FZAPI anyway
             File->ModificationFmt = mfMDHM;

+ 1 - 1
core/Queue.cpp

@@ -262,7 +262,7 @@ __fastcall TTerminalQueue::TTerminalQueue(TTerminal * Terminal,
   FOnListUpdate = NULL;
   FOnEvent = NULL;
   FLastIdle = Now();
-  FIdleInterval = EncodeTime(0, 0, 2, 0);
+  FIdleInterval = EncodeTimeVerbose(0, 0, 2, 0);
 
   assert(Terminal != NULL);
   FSessionData = new TSessionData("");

+ 6 - 4
core/RemoteFiles.cpp

@@ -112,7 +112,7 @@ bool __fastcall ExtractCommonPath(TStrings * Files, AnsiString & Path)
   {
     for (int Index = 1; Index < Files->Count; Index++)
     {
-      while (Path.IsEmpty() &&
+      while (!Path.IsEmpty() &&
         (Files->Strings[Index].SubString(1, Path.Length()) != Path))
       {
         int PrevLen = Path.Length();
@@ -120,6 +120,7 @@ bool __fastcall ExtractCommonPath(TStrings * Files, AnsiString & Path)
         if (Path.Length() == PrevLen)
         {
           Path = "";
+          Result = false;
         }
       }
     }
@@ -138,7 +139,7 @@ bool __fastcall UnixExtractCommonPath(TStrings * Files, AnsiString & Path)
   {
     for (int Index = 1; Index < Files->Count; Index++)
     {
-      while (Path.IsEmpty() &&
+      while (!Path.IsEmpty() &&
         (Files->Strings[Index].SubString(1, Path.Length()) != Path))
       {
         int PrevLen = Path.Length();
@@ -146,6 +147,7 @@ bool __fastcall UnixExtractCommonPath(TStrings * Files, AnsiString & Path)
         if (Path.Length() == PrevLen)
         {
           Path = "";
+          Result = false;
         }
       }
     }
@@ -359,7 +361,7 @@ TDateTime __fastcall ReduceDateTimePrecision(TDateTime DateTime,
         assert(false);
     }
 
-    DateTime = EncodeDate(Y, M, D) + EncodeTime(H, N, S, MS);
+    DateTime = EncodeDateVerbose(Y, M, D) + EncodeTimeVerbose(H, N, S, MS);
   }
   return DateTime;
 }
@@ -1157,7 +1159,7 @@ void __fastcall TRemoteFile::SetListingStr(AnsiString value)
         }
       }
 
-      FModification = EncodeDate(Year, Month, Day) + EncodeTime(Hour, Min, Sec, 0);
+      FModification = EncodeDateVerbose(Year, Month, Day) + EncodeTimeVerbose(Hour, Min, Sec, 0);
       // adjust only when time is known,
       // adjusting default "midnight" time makes no sense
       if ((FModificationFmt == mfMDHM) || (FModificationFmt == mfFull))

+ 16 - 15
core/ScpFileSystem.cpp

@@ -1554,6 +1554,13 @@ void __fastcall TSCPFileSystem::SCPSource(const AnsiString FileName,
 
   OperationProgress->SetFile(FileName, false);
 
+  if (FLAGCLEAR(Params, cpDelete) &&
+      !FTerminal->AllowLocalFileTransfer(FileName, CopyParam))
+  {
+    FTerminal->LogEvent(FORMAT("File \"%s\" excluded from transfer", (FileName)));
+    THROW_SKIP_FILE_NULL;
+  }
+
   HANDLE File;
   int Attrs;
   __int64 MTime, ATime;
@@ -1562,21 +1569,10 @@ void __fastcall TSCPFileSystem::SCPSource(const AnsiString FileName,
   FTerminal->OpenLocalFile(FileName, GENERIC_READ,
     &Attrs, &File, NULL, &MTime, &ATime, &Size);
 
+  bool Dir = FLAGSET(Attrs, faDirectory);
   TStream * Stream = new TSafeHandleStream((THandle)File);
   try
   {
-    bool Dir = FLAGSET(Attrs, faDirectory);
-
-    TFileMasks::TParams MaskParams;
-    MaskParams.Size = Size;
-
-    if (FLAGCLEAR(Params, cpDelete) &&
-        !CopyParam->AllowTransfer(FileName, osLocal, Dir, MaskParams))
-    {
-      FTerminal->LogEvent(FORMAT("File \"%s\" excluded from transfer", (FileName)));
-      THROW_SKIP_FILE_NULL;
-    }
-
     OperationProgress->SetFileInProgress();
 
     if (Dir)
@@ -1600,6 +1596,8 @@ void __fastcall TSCPFileSystem::SCPSource(const AnsiString FileName,
       OperationProgress->TransferingFile = false;
 
       // Will we use ASCII of BINARY file tranfer?
+      TFileMasks::TParams MaskParams;
+      MaskParams.Size = Size;
       OperationProgress->SetAsciiTransfer(
         CopyParam->UseAsciiTransfer(FileName, osLocal, MaskParams));
       FTerminal->LogEvent(
@@ -1819,9 +1817,12 @@ void __fastcall TSCPFileSystem::SCPSource(const AnsiString FileName,
   /* TODO : Delete also read-only files. */
   if (FLAGSET(Params, cpDelete))
   {
-    FILE_OPERATION_LOOP (FMTLOAD(DELETE_LOCAL_FILE_ERROR, (FileName)),
-      THROWOSIFFALSE(Sysutils::DeleteFile(FileName));
-    )
+    if (!Dir)
+    {
+      FILE_OPERATION_LOOP (FMTLOAD(DELETE_LOCAL_FILE_ERROR, (FileName)),
+        THROWOSIFFALSE(Sysutils::DeleteFile(FileName));
+      )
+    }
   }
   else if (CopyParam->ClearArchive && FLAGSET(Attrs, faArchive))
   {

+ 1 - 1
core/SecureShell.cpp

@@ -294,13 +294,13 @@ void __fastcall TSecureShell::StoreToConfig(TSessionData * Data, Config * cfg, b
 //---------------------------------------------------------------------------
 void __fastcall TSecureShell::Open()
 {
+  FBackend = &ssh_backend;
   ResetConnection();
 
   FAuthenticating = false;
   FAuthenticated = false;
 
   Active = false;
-  FBackend = &ssh_backend;
 
   FAuthenticationLog = "";
   FUI->Information(LoadStr(STATUS_LOOKUPHOST), true);

+ 38 - 40
core/SessionData.cpp

@@ -1142,41 +1142,24 @@ void __fastcall TSessionData::ValidateName(const AnsiString Name)
 //---------------------------------------------------------------------
 AnsiString __fastcall TSessionData::EncryptPassword(const AnsiString & Password, AnsiString Key)
 {
-  if (Password.IsEmpty())
-  {
-    return AnsiString();
-  }
-  else
-  {
-    return Configuration->EncryptPassword(Password, Key);
-  }
+  return Configuration->EncryptPassword(Password, Key);
 }
 //---------------------------------------------------------------------
 AnsiString __fastcall TSessionData::StronglyRecryptPassword(const AnsiString & Password, AnsiString Key)
 {
-  if (Password.IsEmpty())
-  {
-    return AnsiString();
-  }
-  else
-  {
-    return Configuration->StronglyRecryptPassword(Password, Key);
-  }
+  return Configuration->StronglyRecryptPassword(Password, Key);
 }
 //---------------------------------------------------------------------
 AnsiString __fastcall TSessionData::DecryptPassword(const AnsiString & Password, AnsiString Key)
 {
   AnsiString Result;
-  if (!Password.IsEmpty())
+  try
   {
-    try
-    {
-      Result = Configuration->DecryptPassword(Password, Key);
-    }
-    catch(EAbort &)
-    {
-      // silently ignore aborted prompts for master password and return empty password
-    }
+    Result = Configuration->DecryptPassword(Password, Key);
+  }
+  catch(EAbort &)
+  {
+    // silently ignore aborted prompts for master password and return empty password
   }
   return Result;
 }
@@ -2032,6 +2015,17 @@ AnsiString __fastcall TSessionData::GetInfoTip()
       (HostName, UserName, FSProtocolStr));
   }
 }
+//---------------------------------------------------------------------
+AnsiString __fastcall TSessionData::GetLocalName()
+{
+  AnsiString Result = Name;
+  int P = Result.LastDelimiter("/");
+  if (P > 0)
+  {
+    Result.Delete(1, P);
+  }
+  return Result;
+}
 //=== TStoredSessionList ----------------------------------------------
 __fastcall TStoredSessionList::TStoredSessionList(bool aReadOnly):
   TNamedObjectList(), FReadOnly(aReadOnly)
@@ -2134,30 +2128,34 @@ void __fastcall TStoredSessionList::Load()
   }
 }
 //---------------------------------------------------------------------
+void __fastcall TStoredSessionList::DoSave(THierarchicalStorage * Storage,
+  TSessionData * Data, bool All, bool RecryptPasswordOnly,
+  TSessionData * FactoryDefaults)
+{
+  if (All || Data->Modified)
+  {
+    if (RecryptPasswordOnly)
+    {
+      Data->SaveRecryptedPasswords(Storage);
+    }
+    else
+    {
+      Data->Save(Storage, false, FactoryDefaults);
+    }
+  }
+}
+//---------------------------------------------------------------------
 void __fastcall TStoredSessionList::DoSave(THierarchicalStorage * Storage,
   bool All, bool RecryptPasswordOnly)
 {
   TSessionData * FactoryDefaults = new TSessionData("");
   try
   {
-    if (All || FDefaultSettings->Modified)
-    {
-      FDefaultSettings->Save(Storage, false, FactoryDefaults);
-    }
+    DoSave(Storage, FDefaultSettings, All, RecryptPasswordOnly, FactoryDefaults);
     for (int Index = 0; Index < Count+HiddenCount; Index++)
     {
       TSessionData * SessionData = (TSessionData *)Items[Index];
-      if (All || SessionData->Modified)
-      {
-        if (RecryptPasswordOnly)
-        {
-          SessionData->SaveRecryptedPasswords(Storage);
-        }
-        else
-        {
-          SessionData->Save(Storage, false, FactoryDefaults);
-        }
-      }
+      DoSave(Storage, SessionData, All, RecryptPasswordOnly, FactoryDefaults);
     }
   }
   __finally

+ 5 - 0
core/SessionData.h

@@ -275,6 +275,7 @@ private:
   void __fastcall SetHostKey(AnsiString value);
   TDateTime __fastcall GetTimeoutDT();
   void __fastcall SavePasswords(THierarchicalStorage * Storage, bool PuttyExport);
+  AnsiString __fastcall GetLocalName();
   static AnsiString __fastcall EncryptPassword(const AnsiString & Password, AnsiString Key);
   static AnsiString __fastcall DecryptPassword(const AnsiString & Password, AnsiString Key);
   static AnsiString __fastcall StronglyRecryptPassword(const AnsiString & Password, AnsiString Key);
@@ -417,6 +418,7 @@ public:
   __property AnsiString StorageKey = { read = GetStorageKey };
   __property AnsiString OrigHostName = { read = FOrigHostName };
   __property int OrigPortNumber = { read = FOrigPortNumber };
+  __property AnsiString LocalName = { read = GetLocalName };
 };
 //---------------------------------------------------------------------------
 class TStoredSessionList : public TNamedObjectList
@@ -456,6 +458,9 @@ private:
   void __fastcall SetDefaultSettings(TSessionData * value);
   void __fastcall DoSave(THierarchicalStorage * Storage, bool All, bool RecryptPasswordOnly);
   void __fastcall DoSave(bool All, bool Explicit, bool RecryptPasswordOnly);
+  void __fastcall DoSave(THierarchicalStorage * Storage,
+    TSessionData * Data, bool All, bool RecryptPasswordOnly,
+    TSessionData * FactoryDefaults);
 };
 //---------------------------------------------------------------------------
 #endif

+ 17 - 15
core/SftpFileSystem.cpp

@@ -3904,6 +3904,13 @@ void __fastcall TSFTPFileSystem::SFTPSource(const AnsiString FileName,
 
   OperationProgress->SetFile(FileName, false);
 
+  if (FLAGCLEAR(Params, cpDelete) &&
+      !FTerminal->AllowLocalFileTransfer(FileName, CopyParam))
+  {
+    FTerminal->LogEvent(FORMAT("File \"%s\" excluded from transfer", (FileName)));
+    THROW_SKIP_FILE_NULL;
+  }
+
   TOpenRemoteFileParams OpenParams;
   OpenParams.OverwriteMode = omOverwrite;
 
@@ -3914,20 +3921,10 @@ void __fastcall TSFTPFileSystem::SFTPSource(const AnsiString FileName,
   FTerminal->OpenLocalFile(FileName, GENERIC_READ, &OpenParams.LocalFileAttrs,
     &File, NULL, &MTime, &ATime, &Size);
 
+  bool Dir = FLAGSET(OpenParams.LocalFileAttrs, faDirectory);
+
   try
   {
-    bool Dir = FLAGSET(OpenParams.LocalFileAttrs, faDirectory);
-
-    TFileMasks::TParams MaskParams;
-    MaskParams.Size = Size;
-
-    if (FLAGCLEAR(Params, cpDelete) &&
-        !CopyParam->AllowTransfer(FileName, osLocal, Dir, MaskParams))
-    {
-      FTerminal->LogEvent(FORMAT("File \"%s\" excluded from transfer", (FileName)));
-      THROW_SKIP_FILE_NULL;
-    }
-
     OperationProgress->SetFileInProgress();
 
     if (Dir)
@@ -3962,6 +3959,8 @@ void __fastcall TSFTPFileSystem::SFTPSource(const AnsiString FileName,
       OperationProgress->TransferingFile = false;
 
       // Will we use ASCII of BINARY file tranfer?
+      TFileMasks::TParams MaskParams;
+      MaskParams.Size = Size;
       OperationProgress->SetAsciiTransfer(
         CopyParam->UseAsciiTransfer(FileName, osLocal, MaskParams));
       FTerminal->LogEvent(
@@ -4299,9 +4298,12 @@ void __fastcall TSFTPFileSystem::SFTPSource(const AnsiString FileName,
   /* TODO : Delete also read-only files. */
   if (FLAGSET(Params, cpDelete))
   {
-    FILE_OPERATION_LOOP (FMTLOAD(DELETE_LOCAL_FILE_ERROR, (FileName)),
-      THROWOSIFFALSE(Sysutils::DeleteFile(FileName));
-    )
+    if (!Dir)
+    {
+      FILE_OPERATION_LOOP (FMTLOAD(DELETE_LOCAL_FILE_ERROR, (FileName)),
+        THROWOSIFFALSE(Sysutils::DeleteFile(FileName));
+      )
+    }
   }
   else if (CopyParam->ClearArchive && FLAGSET(OpenParams.LocalFileAttrs, faArchive))
   {

+ 100 - 74
core/Terminal.cpp

@@ -570,29 +570,19 @@ void __fastcall TTerminal::Idle()
 //---------------------------------------------------------------------
 AnsiString __fastcall TTerminal::EncryptPassword(const AnsiString & Password)
 {
-  if (Password.IsEmpty())
-  {
-    return AnsiString();
-  }
-  else
-  {
-    return Configuration->EncryptPassword(Password, SessionData->SessionName);
-  }
+  return Configuration->EncryptPassword(Password, SessionData->SessionName);
 }
 //---------------------------------------------------------------------
 AnsiString __fastcall TTerminal::DecryptPassword(const AnsiString & Password)
 {
   AnsiString Result;
-  if (!Password.IsEmpty())
+  try
   {
-    try
-    {
-      Result = Configuration->DecryptPassword(Password, SessionData->SessionName);
-    }
-    catch(EAbort &)
-    {
-      // silently ignore aborted prompts for master password and return empty password
-    }
+    Result = Configuration->DecryptPassword(Password, SessionData->SessionName);
+  }
+  catch(EAbort &)
+  {
+    // silently ignore aborted prompts for master password and return empty password
   }
   return Result;
 }
@@ -3521,81 +3511,91 @@ void __fastcall TTerminal::DoAnyCommand(const AnsiString Command,
   }
 }
 //---------------------------------------------------------------------------
-bool __fastcall TTerminal::CreateLocalFile(const AnsiString FileName,
+bool __fastcall TTerminal::DoCreateLocalFile(const AnsiString FileName,
   TFileOperationProgressType * OperationProgress, HANDLE * AHandle,
   bool NoConfirmation)
 {
-  assert(AHandle);
   bool Result = true;
-
-  FILE_OPERATION_LOOP (FMTLOAD(CREATE_FILE_ERROR, (FileName)),
-    bool Done;
-    unsigned int CreateAttr = FILE_ATTRIBUTE_NORMAL;
-    do
-    {
-      *AHandle = CreateFile(FileName.c_str(), GENERIC_WRITE, FILE_SHARE_READ,
-        NULL, CREATE_ALWAYS, CreateAttr, 0);
-      Done = (*AHandle != INVALID_HANDLE_VALUE);
-      if (!Done)
+  bool Done;
+  unsigned int CreateAttr = FILE_ATTRIBUTE_NORMAL;
+  do
+  {
+    *AHandle = CreateFile(FileName.c_str(), GENERIC_WRITE, FILE_SHARE_READ,
+      NULL, CREATE_ALWAYS, CreateAttr, 0);
+    Done = (*AHandle != INVALID_HANDLE_VALUE);
+    if (!Done)
+    {
+      int FileAttr;
+      if (::FileExists(FileName) &&
+        (((FileAttr = FileGetAttr(FileName)) & (faReadOnly | faHidden)) != 0))
       {
-        int FileAttr;
-        if (FileExists(FileName) &&
-          (((FileAttr = FileGetAttr(FileName)) & (faReadOnly | faHidden)) != 0))
+        if (FLAGSET(FileAttr, faReadOnly))
         {
-          if (FLAGSET(FileAttr, faReadOnly))
+          if (OperationProgress->BatchOverwrite == boNone)
           {
-            if (OperationProgress->BatchOverwrite == boNone)
-            {
-              Result = false;
-            }
-            else if ((OperationProgress->BatchOverwrite != boAll) && !NoConfirmation)
-            {
-              int Answer;
-              SUSPEND_OPERATION
-              (
-                Answer = QueryUser(
-                  FMTLOAD(READ_ONLY_OVERWRITE, (FileName)), NULL,
-                  qaYes | qaNo | qaCancel | qaYesToAll | qaNoToAll, 0);
-              );
-              switch (Answer) {
-                case qaYesToAll: OperationProgress->BatchOverwrite = boAll; break;
-                case qaCancel: OperationProgress->Cancel = csCancel; // continue on next case
-                case qaNoToAll: OperationProgress->BatchOverwrite = boNone;
-                case qaNo: Result = false; break;
-              }
-            }
+            Result = false;
           }
-          else
+          else if ((OperationProgress->BatchOverwrite != boAll) && !NoConfirmation)
           {
-            assert(FLAGSET(FileAttr, faHidden));
-            Result = true;
+            int Answer;
+            SUSPEND_OPERATION
+            (
+              Answer = QueryUser(
+                FMTLOAD(READ_ONLY_OVERWRITE, (FileName)), NULL,
+                qaYes | qaNo | qaCancel | qaYesToAll | qaNoToAll, 0);
+            );
+            switch (Answer) {
+              case qaYesToAll: OperationProgress->BatchOverwrite = boAll; break;
+              case qaCancel: OperationProgress->Cancel = csCancel; // continue on next case
+              case qaNoToAll: OperationProgress->BatchOverwrite = boNone;
+              case qaNo: Result = false; break;
+            }
           }
+        }
+        else
+        {
+          assert(FLAGSET(FileAttr, faHidden));
+          Result = true;
+        }
 
-          if (Result)
-          {
-            CreateAttr |=
-              FLAGMASK(FLAGSET(FileAttr, faHidden), FILE_ATTRIBUTE_HIDDEN) |
-              FLAGMASK(FLAGSET(FileAttr, faReadOnly), FILE_ATTRIBUTE_READONLY);
+        if (Result)
+        {
+          CreateAttr |=
+            FLAGMASK(FLAGSET(FileAttr, faHidden), FILE_ATTRIBUTE_HIDDEN) |
+            FLAGMASK(FLAGSET(FileAttr, faReadOnly), FILE_ATTRIBUTE_READONLY);
 
-            FILE_OPERATION_LOOP (FMTLOAD(CANT_SET_ATTRS, (FileName)),
-              if (FileSetAttr(FileName, FileAttr & ~(faReadOnly | faHidden)) != 0)
-              {
-                RaiseLastOSError();
-              }
-            );
-          }
-          else
-          {
-            Done = true;
-          }
+          FILE_OPERATION_LOOP (FMTLOAD(CANT_SET_ATTRS, (FileName)),
+            if (FileSetAttr(FileName, FileAttr & ~(faReadOnly | faHidden)) != 0)
+            {
+              RaiseLastOSError();
+            }
+          );
         }
         else
         {
-          RaiseLastOSError();
+          Done = true;
         }
       }
+      else
+      {
+        RaiseLastOSError();
+      }
     }
-    while (!Done);
+  }
+  while (!Done);
+
+  return Result;
+}
+//---------------------------------------------------------------------------
+bool __fastcall TTerminal::CreateLocalFile(const AnsiString FileName,
+  TFileOperationProgressType * OperationProgress, HANDLE * AHandle,
+  bool NoConfirmation)
+{
+  assert(AHandle);
+  bool Result = true;
+
+  FILE_OPERATION_LOOP (FMTLOAD(CREATE_FILE_ERROR, (FileName)),
+    Result = DoCreateLocalFile(FileName, OperationProgress, AHandle, NoConfirmation);
   );
 
   return Result;
@@ -3689,6 +3689,32 @@ void __fastcall TTerminal::OpenLocalFile(const AnsiString FileName,
   if (AHandle) *AHandle = Handle;
 }
 //---------------------------------------------------------------------------
+bool __fastcall TTerminal::AllowLocalFileTransfer(AnsiString FileName,
+  const TCopyParamType * CopyParam)
+{
+  bool Result = true;
+  if (!CopyParam->AllowAnyTransfer())
+  {
+    WIN32_FIND_DATA FindData;
+    HANDLE Handle;
+    FILE_OPERATION_LOOP (FMTLOAD(FILE_NOT_EXISTS, (FileName)),
+      Handle = FindFirstFile(FileName.c_str(), &FindData);
+      if (Handle == INVALID_HANDLE_VALUE)
+      {
+        Abort();
+      }
+    )
+    ::FindClose(Handle);
+    bool Directory = FLAGSET(FindData.dwFileAttributes, FILE_ATTRIBUTE_DIRECTORY);
+    TFileMasks::TParams Params;
+    Params.Size =
+      (static_cast<__int64>(FindData.nFileSizeHigh) << 32) +
+      FindData.nFileSizeLow;
+    Result = CopyParam->AllowTransfer(FileName, osLocal, Directory, Params);
+  }
+  return Result;
+}
+//---------------------------------------------------------------------------
 AnsiString __fastcall TTerminal::FileUrl(const AnsiString Protocol,
   const AnsiString FileName)
 {

+ 4 - 0
core/Terminal.h

@@ -267,6 +267,7 @@ protected:
   void __fastcall OpenLocalFile(const AnsiString FileName, int Access,
     int * Attrs, HANDLE * Handle, __int64 * ACTime, __int64 * MTime,
     __int64 * ATime, __int64 * Size, bool TryWriteReadOnly = true);
+  bool __fastcall AllowLocalFileTransfer(AnsiString FileName, const TCopyParamType * CopyParam);
   bool __fastcall HandleException(Exception * E);
   void __fastcall CalculateFileSize(AnsiString FileName,
     const TRemoteFile * File, /*TCalculateSizeParams*/ void * Size);
@@ -315,6 +316,9 @@ protected:
     int MaxLen, AnsiString & Result);
   void __fastcall FileFind(AnsiString FileName, const TRemoteFile * File, void * Param);
   void __fastcall DoFilesFind(AnsiString Directory, TFilesFindParams & Params);
+  bool __fastcall DoCreateLocalFile(const AnsiString FileName,
+    TFileOperationProgressType * OperationProgress, HANDLE * AHandle,
+    bool NoConfirmation);
 
   virtual void __fastcall Information(const AnsiString & Str, bool Status);
   virtual int __fastcall QueryUser(const AnsiString Query,

+ 11 - 0
forms/Console.cpp

@@ -41,6 +41,7 @@ __fastcall TConsoleDialog::TConsoleDialog(TComponent* AOwner)
   FOldChangeDirectory = NULL;
   FPrevTerminalClose = NULL;;
   FLastTerminal = NULL;
+  FAnyCommandExecuted = false;
   OutputMemo->Color = clBlack;
   OutputMemo->Font->Color = (TColor)0x00BBBBBB; //clGray;
   UseSystemSettings(this);
@@ -74,6 +75,15 @@ void __fastcall TConsoleDialog::SetTerminal(TTerminal * value)
       assert(FTerminal->OnChangeDirectory == DoChangeDirectory);
       FTerminal->OnChangeDirectory = FOldChangeDirectory;
       FOldChangeDirectory = NULL;
+      if (FAnyCommandExecuted)
+      {
+        FAnyCommandExecuted = false;
+        // directory would be read from EndTransaction anyway,
+        // but with reload only flat set, what prevents
+        // recording path in history, what we want if the path was
+        // changed by "cd" command in console
+        FTerminal->ReadDirectory(false);
+      }
       FTerminal->EndTransaction();
     }
     FTerminal = value;
@@ -181,6 +191,7 @@ void __fastcall TConsoleDialog::DoExecuteCommand()
   {
     AnsiString Command = CommandEdit->Text;
     OutputMemo->Lines->Add(FORMAT("%s$ %s", (FTerminal->CurrentDirectory, Command)));
+    FAnyCommandExecuted = true;
     FTerminal->AnyCommand(Command, AddLine);
   }
   __finally

+ 1 - 0
forms/Console.h

@@ -62,6 +62,7 @@ private:
   TNotifyEvent FPrevTerminalClose;
   TRect FAutoBounds;
   bool FClearExceptionOnFail;
+  bool FAnyCommandExecuted;
 
   void __fastcall DoExecuteCommand();
   void __fastcall ExecuteCommand();

+ 5 - 4
forms/Custom.cpp

@@ -265,6 +265,11 @@ void __fastcall TSaveSessionDialog::DoShow()
 void __fastcall TSaveSessionDialog::DoValidate()
 {
   SessionNameValidate(SessionNameCombo->Text, FOriginalSession);
+  if (SavePasswordCheck->Enabled && SavePasswordCheck->Checked &&
+      CustomWinConfiguration->UseMasterPassword)
+  {
+    CustomWinConfiguration->AskForMasterPasswordIfNotSet();
+  }
   TCustomDialog::DoValidate();
 }
 //---------------------------------------------------------------------------
@@ -288,10 +293,6 @@ bool __fastcall DoSaveSessionDialog(AnsiString & SessionName,
       SavePassword = &Dummy;
     }
     Result = Dialog->Execute(SessionName, *SavePassword);
-    if (Result && (SavePassword != NULL) && *SavePassword)
-    {
-      CustomWinConfiguration->AskForMasterPasswordIfNotSet();
-    }
   }
   __finally
   {

+ 7 - 6
forms/CustomScpExplorer.cpp

@@ -575,9 +575,9 @@ void __fastcall TCustomScpExplorerForm::UpdateTransferList()
     }
     // this way we get name for "default" settings (COPY_PARAM_DEFAULT)
     AnsiString Name = TransferList->Strings->Strings[TransferList->ItemIndex];
-    TransferDropDown->Text = Name;
+    TransferDropDown->Text = StripHotkey(Name);
     TransferDropDown->Hint = FORMAT("%s\n \n%s:\n%s|%s",
-      (FTransferDropDownHint, Name,
+      (FTransferDropDownHint, StripHotkey(Name),
        GUIConfiguration->CurrentCopyParam.GetInfoStr("; ",
          FLAGMASK(Terminal != NULL, Terminal->UsableCopyParamAttrs(0).General)),
        FTransferDropDownHint));
@@ -1984,7 +1984,7 @@ void __fastcall TCustomScpExplorerForm::TemporaryDirectoryForRemoteFiles(
 
   if (WinConfiguration->TemporaryDirectoryAppendSession)
   {
-    Result += IncludeTrailingBackslash(CopyParam.ValidLocalPath(Terminal->SessionData->SessionName));
+    Result = IncludeTrailingBackslash(Result + CopyParam.ValidLocalPath(Terminal->SessionData->SessionName));
   }
 
   if (WinConfiguration->TemporaryDirectoryAppendPath)
@@ -1993,7 +1993,7 @@ void __fastcall TCustomScpExplorerForm::TemporaryDirectoryForRemoteFiles(
     {
       RemoteDirectory.Delete(1, 1);
     }
-    Result += IncludeTrailingBackslash(CopyParam.ValidLocalPath(FromUnixPath(RemoteDirectory)));
+    Result = IncludeTrailingBackslash(Result + CopyParam.ValidLocalPath(FromUnixPath(RemoteDirectory)));
   }
 
   if (!ForceDirectories(Result))
@@ -2956,7 +2956,8 @@ void __fastcall TCustomScpExplorerForm::UpdateStatusBar()
   if (FShowStatusBarHint)
   {
     SessionStatusBar->SimplePanel = true;
-    SessionStatusBar->SimpleText = FStatusBarHint;
+    // escape hotkeys particularly because of the custom commands names
+    SessionStatusBar->SimpleText = EscapeHotkey(FStatusBarHint);
   }
   else if (!Terminal || !Terminal->Active || Terminal->Status < ssOpened)
   {
@@ -6145,7 +6146,7 @@ bool __fastcall TCustomScpExplorerForm::CancelNote()
   {
     // cannot cancel note too early
     if (Now() - FNoteShown >
-          EncodeTime(0, 0, (unsigned short)(WinConfiguration->NotificationsStickTime), 0))
+          EncodeTimeVerbose(0, 0, (unsigned short)(WinConfiguration->NotificationsStickTime), 0))
     {
       FNoteTimer->Enabled = false;
       FNote = "";

+ 6 - 1
forms/FileFind.cpp

@@ -222,7 +222,12 @@ void __fastcall TFileFindDialog::FileFound(TTerminal * /*Terminal*/,
   Item->Data = File;
 
   Item->ImageIndex = File->IconIndex;
-  Item->Caption = File->FileName;
+  AnsiString Caption = File->FileName;
+  if (File->IsDirectory)
+  {
+    Caption = UnixIncludeTrailingBackslash(Caption);
+  }
+  Item->Caption = Caption;
 
   AnsiString Directory = UnixExtractFilePath(File->FullFileName);
   if (AnsiSameText(FDirectory, Directory.SubString(1, FDirectory.Length())))

+ 4 - 4
forms/FullSynchronize.dfm

@@ -229,19 +229,19 @@ object FullSynchronizeDialog: TFullSynchronizeDialog
   end
   object SaveSettingsCheck: TCheckBox
     Left = 19
-    Top = 372
+    Top = 317
     Width = 246
     Height = 17
     Caption = 'Use &same options next time'
-    TabOrder = 6
+    TabOrder = 5
   end
   object CopyParamGroup: TGroupBox
     Left = 8
-    Top = 316
+    Top = 338
     Width = 417
     Height = 50
     Caption = 'Transfer settings'
-    TabOrder = 5
+    TabOrder = 6
     OnContextPopup = CopyParamGroupContextPopup
     OnDblClick = CopyParamGroupDblClick
     DesignSize = (

+ 13 - 7
forms/Login.cpp

@@ -1133,11 +1133,17 @@ void __fastcall TLoginDialog::UpdateControls()
       // preferences sheet
       GeneralSheet->Enabled = FLAGSET(Options, loPreferences);
 
-      TSessionData * Data = SessionData;
-      bool CanLogin = (Data != NULL) && Data->CanLogin;
-      bool SessionSelected =
-        (SessionTree->Selected != NULL) && (SessionTree->Selected->Data != NULL);
-      LoginButton->Default = CanLogin || !SessionSelected;
+      // this methods saves us from calling GetSessionData,
+      // which breaks changing locale (session data are not preserved,
+      // as we would overwrite them with non-initialized control data)
+      if (PageControl->ActivePage == SessionListSheet)
+      {
+        LoginButton->Default = (SelectedSession != NULL) && SelectedSession->CanLogin;
+      }
+      else
+      {
+        LoginButton->Default = true;
+      }
       LoadButton->Default = !LoginButton->Default;
 
       AboutButton->Visible = (Options & loAbout);
@@ -1805,7 +1811,7 @@ void __fastcall TLoginDialog::DesktopIconActionExecute(TObject * /*Sender*/)
         qtConfirmation, qaYes | qaNo, HELP_CREATE_SHORTCUT) == qaYes)
   {
     assert(SelectedSession);
-    CreateDesktopShortCut(SelectedSession->Name, Application->ExeName,
+    CreateDesktopShortCut(SelectedSession->LocalName, Application->ExeName,
       FORMAT("\"%s\" /UploadIfAny", (SelectedSession->Name)),
       FMTLOAD(SHORTCUT_INFO_TIP, (SelectedSession->Name, SelectedSession->InfoTip)));
   }
@@ -1817,7 +1823,7 @@ void __fastcall TLoginDialog::SendToHookActionExecute(TObject * /*Sender*/)
         qtConfirmation, qaYes | qaNo, HELP_CREATE_SENDTO) == qaYes)
   {
     assert(SelectedSession);
-    CreateDesktopShortCut(FMTLOAD(SESSION_SENDTO_HOOK_NAME, (SelectedSession->Name)),
+    CreateDesktopShortCut(FMTLOAD(SESSION_SENDTO_HOOK_NAME, (SelectedSession->LocalName)),
       Application->ExeName,
       FORMAT("\"%s\" /Upload", (SelectedSession->Name)), "",
       CSIDL_SENDTO);

+ 5 - 3
forms/NonVisual.cpp

@@ -772,6 +772,7 @@ void __fastcall TNonVisualDataModule::ExplorerShortcuts()
   RestoreSelectionAction->ShortCut = ShortCut('R', CTRLALT);
   // commands
   NewFileAction->ShortCut = ShortCut('E', CTRLSHIFT);
+  FindFilesAction->ShortCut = ShortCut(VK_F3, NONE);
 
   CloseApplicationAction->ShortCut = ShortCut(VK_F4, ALT);
 }
@@ -825,6 +826,7 @@ void __fastcall TNonVisualDataModule::CommanderShortcuts()
   RestoreSelectionAction->ShortCut = ShortCut('R', CTRLALT);
   // commands
   NewFileAction->ShortCut = ShortCut(VK_F4, SHIFT);
+  FindFilesAction->ShortCut = ShortCut(VK_F7, ALT);
   // legacy shortcut (can be removed when necessary)
   NewFileAction->SecondaryShortCuts->Add(ShortCutToText(ShortCut(VK_F4, CTRLSHIFT)));
 
@@ -886,7 +888,7 @@ void __fastcall TNonVisualDataModule::CreateCustomCommandsMenu(
       Item->Caption = Command->Name;
       if (Toolbar)
       {
-        Item->Caption = StripHotkey(Item->Caption);
+        Item->Caption = EscapeHotkey(StripHotkey(Item->Caption));
       }
       Item->Tag = Index;
       Item->Enabled = (State > 0);
@@ -921,7 +923,7 @@ void __fastcall TNonVisualDataModule::CreateCustomCommandsMenu(
     Item->Action = OnFocused ? CustomCommandsLastFocusedAction : CustomCommandsLastAction;
     if (Toolbar)
     {
-      Item->Caption = StripHotkey(LoadStr(CUSTOM_COMMAND_LAST_SHORT));
+      Item->Caption = EscapeHotkey(StripHotkey(LoadStr(CUSTOM_COMMAND_LAST_SHORT)));
     }
     Menu->Add(Item);
   }
@@ -976,7 +978,7 @@ void __fastcall TNonVisualDataModule::UpdateCustomCommandsToolbar(TTBXToolbar *
     {
       Changed =
         (Toolbar->Items->Items[Index]->Caption !=
-          StripHotkey(CustomCommandList->Commands[Index]->Name));
+          EscapeHotkey(StripHotkey(CustomCommandList->Commands[Index]->Name)));
       Index++;
     }
   }

+ 0 - 1
forms/NonVisual.dfm

@@ -1840,7 +1840,6 @@ object NonVisualDataModule: TNonVisualDataModule
       HelpKeyword = 'task_find'
       Hint = 'Find files|Find files and directories'
       ImageIndex = 95
-      ShortCut = 32886
     end
   end
   object ExplorerBarPopup: TTBXPopupMenu

+ 6 - 5
forms/Preferences.cpp

@@ -849,7 +849,7 @@ void __fastcall TPreferencesDialog::CustomCommandsViewData(TObject * /*Sender*/,
   int Index = Item->Index;
   assert(Index >= 0 && Index <= FCustomCommandList->Count);
   const TCustomCommandType * Command = FCustomCommandList->Commands[Index];
-  AnsiString Caption = StringReplace(Command->Name, "&", "", TReplaceFlags() << rfReplaceAll);
+  AnsiString Caption = StripHotkey(Command->Name);
   if (Command->ShortCut != 0)
   {
     Caption = FORMAT("%s (%s)", (Caption, ShortCutToText(Command->ShortCut)));
@@ -1423,8 +1423,7 @@ void __fastcall TPreferencesDialog::CopyParamListViewData(TObject * /*Sender*/,
 {
   int Index = Item->Index;
   assert(Index >= 0 && Index <= FCopyParamList->Count);
-  Item->Caption = StringReplace(FCopyParamList->Names[Index], "&", "",
-    TReplaceFlags() << rfReplaceAll);
+  Item->Caption = StripHotkey(FCopyParamList->Names[Index]);
   Item->SubItems->Add(BooleanToStr(FCopyParamList->Rules[Index] != NULL));
 }
 //---------------------------------------------------------------------------
@@ -1562,7 +1561,9 @@ void __fastcall TPreferencesDialog::UseMasterPasswordCheckClick(
 void __fastcall TPreferencesDialog::SetMasterPasswordButtonClick(
   TObject * /*Sender*/)
 {
-  DoChangeMasterPasswordDialog();
-  MessageDialog(LoadStr(MASTER_PASSWORD_CHANGED), qtInformation, qaOK, HELP_MASTER_PASSWORD);
+  if (DoChangeMasterPasswordDialog())
+  {
+    MessageDialog(LoadStr(MASTER_PASSWORD_CHANGED), qtInformation, qaOK, HELP_MASTER_PASSWORD);
+  }
 }
 //---------------------------------------------------------------------------

+ 2 - 0
forms/Preferences.dfm

@@ -2018,6 +2018,8 @@ object PreferencesDialog: TPreferencesDialog
       object SecuritySheet: TTabSheet
         Tag = 19
         Hint = 'Security'
+        HelpType = htKeyword
+        HelpKeyword = 'ui_pref_security'
         Caption = 'Security'
         ImageIndex = 18
         TabVisible = False

+ 123 - 62
forms/ScpCommander.cpp

@@ -857,66 +857,96 @@ void __fastcall TScpCommanderForm::FileOperationProgress(
   TCustomScpExplorerForm::FileOperationProgress(ProgressData, Cancel);
 }
 //---------------------------------------------------------------------------
-void __fastcall TScpCommanderForm::SynchronizeBrowsing(TCustomDirView * ADirView,
+AnsiString __fastcall TScpCommanderForm::ChangeFilePath(AnsiString Path, TOperationSide Side)
+{
+  TGUICopyParamType CopyParams = GUIConfiguration->CurrentCopyParam;
+  AnsiString Result;
+  while (!Path.IsEmpty())
+  {
+    int P = Path.Pos(Side == osLocal ? '\\' : '/');
+    if (P > 0)
+    {
+      Result += CopyParams.ChangeFileName(Path.SubString(1, P - 1), Side, false) +
+        (Side == osLocal ? '/' : '\\');
+      Path.Delete(1, P);
+    }
+    else
+    {
+      Result += CopyParams.ChangeFileName(Path, osLocal, false);
+      Path = "";
+    }
+  }
+
+  return Result;
+}
+//---------------------------------------------------------------------------
+void __fastcall TScpCommanderForm::SynchronizeBrowsingLocal(
   AnsiString PrevPath, AnsiString & NewPath, bool Create)
 {
-  if (ADirView == LocalDirView)
+  Terminal->ExceptionOnFail = true;
+  TStrings * Paths = new TStringList();
+  try
   {
-    Terminal->ExceptionOnFail = true;
-    try
+    Paths->Add(PrevPath);
+    Paths->Add(LocalDirView->Path);
+    AnsiString CommonPath;
+    if (ExtractCommonPath(Paths, CommonPath))
     {
-      AnsiString FullPrevPath = IncludeTrailingBackslash(PrevPath);
-      if (LocalDirView->Path.SubString(1, FullPrevPath.Length()) == FullPrevPath)
-      {
-        NewPath = UnixIncludeTrailingBackslash(RemoteDirView->Path) +
-          ToUnixPath(LocalDirView->Path.SubString(FullPrevPath.Length() + 1,
-            LocalDirView->Path.Length() - FullPrevPath.Length()));
-      }
-      else if (FullPrevPath.SubString(1, LocalDirView->Path.Length()) == LocalDirView->Path)
+      PrevPath = IncludeTrailingBackslash(PrevPath);
+      CommonPath = IncludeTrailingBackslash(CommonPath);
+      NewPath = RemoteDirView->Path;
+      while (!ComparePaths(PrevPath, CommonPath))
       {
-        NewPath = RemoteDirView->Path;
-        while (!ComparePaths(FullPrevPath, LocalDirView->Path))
+        if (NewPath == UnixExcludeTrailingBackslash(NewPath))
         {
-          if (NewPath == UnixExcludeTrailingBackslash(NewPath))
-          {
-            Abort();
-          }
-          NewPath = UnixExtractFilePath(UnixExcludeTrailingBackslash(NewPath));
-          FullPrevPath = ExtractFilePath(ExcludeTrailingBackslash(FullPrevPath));
+          Abort();
         }
-      }
-      else
-      {
-        Abort();
+        NewPath = UnixExtractFilePath(UnixExcludeTrailingBackslash(NewPath));
+        PrevPath = ExtractFilePath(ExcludeTrailingBackslash(PrevPath));
       }
 
-      if (Create)
-      {
-        TRemoteProperties Properties = GUIConfiguration->NewDirectoryProperties;
-        RemoteDirView->CreateDirectoryEx(NewPath, &Properties);
-      }
-
-      RemoteDirView->Path = NewPath;
+      NewPath = UnixIncludeTrailingBackslash(NewPath) +
+        ToUnixPath(LocalDirView->Path.SubString(PrevPath.Length() + 1,
+          LocalDirView->Path.Length() - PrevPath.Length()));
     }
-    __finally
+    else
     {
-      Terminal->ExceptionOnFail = false;
+      Abort();
     }
-  }
-  else
-  {
-    AnsiString FullPrevPath = UnixIncludeTrailingBackslash(PrevPath);
-    if (RemoteDirView->Path.SubString(1, FullPrevPath.Length()) == FullPrevPath)
+
+    if (Create)
     {
-      NewPath = IncludeTrailingBackslash(LocalDirView->Path) +
-        FromUnixPath(RemoteDirView->Path.SubString(FullPrevPath.Length() + 1,
-          RemoteDirView->Path.Length() - FullPrevPath.Length()));
+      TRemoteProperties Properties = GUIConfiguration->NewDirectoryProperties;
+      RemoteDirView->CreateDirectoryEx(NewPath, &Properties);
     }
-    else if (FullPrevPath.SubString(1, RemoteDirView->Path.Length()) == RemoteDirView->Path)
+
+    RemoteDirView->Path = NewPath;
+  }
+  __finally
+  {
+    Terminal->ExceptionOnFail = false;
+    delete Paths;
+  }
+}
+//---------------------------------------------------------------------------
+void __fastcall TScpCommanderForm::SynchronizeBrowsingRemote(
+  AnsiString PrevPath, AnsiString & NewPath, bool Create)
+{
+  TStrings * Paths = new TStringList();
+  try
+  {
+    Paths->Add(UnixIncludeTrailingBackslash(PrevPath));
+    Paths->Add(UnixIncludeTrailingBackslash(RemoteDirView->Path));
+    AnsiString CommonPath;
+
+    if (UnixExtractCommonPath(Paths, CommonPath))
     {
+      PrevPath = UnixIncludeTrailingBackslash(PrevPath);
+      CommonPath = UnixIncludeTrailingBackslash(CommonPath);
+
       AnsiString NewLocalPath;
       NewPath = ExcludeTrailingBackslash(LocalDirView->Path);
-      while (!UnixComparePaths(FullPrevPath, RemoteDirView->Path))
+      while (!UnixComparePaths(PrevPath, CommonPath))
       {
         NewLocalPath = ExcludeTrailingBackslash(ExtractFileDir(NewPath));
         if (NewLocalPath == NewPath)
@@ -924,20 +954,43 @@ void __fastcall TScpCommanderForm::SynchronizeBrowsing(TCustomDirView * ADirView
           Abort();
         }
         NewPath = NewLocalPath;
-        FullPrevPath = UnixExtractFilePath(UnixExcludeTrailingBackslash(FullPrevPath));
+        PrevPath = UnixExtractFilePath(UnixExcludeTrailingBackslash(PrevPath));
       }
+
+      NewPath = IncludeTrailingBackslash(NewPath) +
+        ChangeFilePath(
+          RemoteDirView->Path.SubString(PrevPath.Length() + 1,
+            RemoteDirView->Path.Length() - PrevPath.Length()),
+          osRemote);
     }
     else
     {
       Abort();
     }
+  }
+  __finally
+  {
+    delete Paths;
+  }
 
-    if (Create)
-    {
-      LocalDirView->CreateDirectory(NewPath);
-    }
+  if (Create)
+  {
+    LocalDirView->CreateDirectory(NewPath);
+  }
 
-    LocalDirView->Path = NewPath;
+  LocalDirView->Path = NewPath;
+}
+//---------------------------------------------------------------------------
+void __fastcall TScpCommanderForm::SynchronizeBrowsing(TCustomDirView * ADirView,
+  AnsiString PrevPath, AnsiString & NewPath, bool Create)
+{
+  if (ADirView == LocalDirView)
+  {
+    SynchronizeBrowsingLocal(PrevPath, NewPath, Create);
+  }
+  else
+  {
+    SynchronizeBrowsingRemote(PrevPath, NewPath, Create);
   }
 }
 //---------------------------------------------------------------------------
@@ -976,26 +1029,34 @@ void __fastcall TScpCommanderForm::SynchronizeBrowsing(TCustomDirView * ADirView
           }
           else
           {
-            Terminal->ShowExtendedException(&E);
-            if (MessageDialog(FMTLOAD(SYNC_DIR_BROWSE_CREATE, (NewPath)), qtInformation, qaYes | qaNo,
-                  HELP_SYNC_DIR_BROWSE_ERROR) == qaYes)
+            TStrings * MoreMessages = ExceptionToMoreMessages(&E);
+            try
             {
-              try
-              {
-                SynchronizeBrowsing(ADirView, PrevPath, NewPath, true);
-              }
-              catch(Exception & E)
+              if (MoreMessageDialog(FMTLOAD(SYNC_DIR_BROWSE_CREATE, (NewPath)),
+                    MoreMessages, qtConfirmation, qaYes | qaNo,
+                    HELP_SYNC_DIR_BROWSE_ERROR) == qaYes)
               {
-                if (!Application->Terminated)
+                try
                 {
-                  Terminal->ShowExtendedException(&E);
+                  SynchronizeBrowsing(ADirView, PrevPath, NewPath, true);
                 }
-                throw;
+                catch(Exception & E)
+                {
+                  if (!Application->Terminated)
+                  {
+                    Terminal->ShowExtendedException(&E);
+                  }
+                  throw;
+                }
+              }
+              else
+              {
+                NonVisualDataModule->SynchronizeBrowsingAction->Checked = false;
               }
             }
-            else
+            __finally
             {
-              NonVisualDataModule->SynchronizeBrowsingAction->Checked = false;
+              delete MoreMessages;
             }
           }
         }

+ 3 - 0
forms/ScpCommander.h

@@ -501,12 +501,15 @@ protected:
   void __fastcall SynchronizeBrowsing(TCustomDirView * ADirView);
   void __fastcall SynchronizeBrowsing(TCustomDirView * ADirView, AnsiString PrevPath,
     AnsiString & NewPath, bool Create);
+  void __fastcall SynchronizeBrowsingLocal(AnsiString PrevPath, AnsiString & NewPath, bool Create);
+  void __fastcall SynchronizeBrowsingRemote(AnsiString PrevPath, AnsiString & NewPath, bool Create);
   void __fastcall LocalPathComboUpdateDrives();
   void __fastcall LocalPathComboUpdate();
   virtual void __fastcall ToolbarItemResize(TTBXCustomDropDownItem * Item, int Width);
   void __fastcall DoOpenBookmark(AnsiString Local, AnsiString Remote);
   virtual bool __fastcall OpenBookmark(AnsiString Local, AnsiString Remote);
   virtual void __fastcall DoFocusRemotePath(AnsiString Path);
+  AnsiString __fastcall ChangeFilePath(AnsiString Path, TOperationSide Side);
 
 public:
   __fastcall TScpCommanderForm(TComponent* Owner);

+ 1 - 1
forms/SynchronizeProgress.cpp

@@ -23,7 +23,7 @@ __fastcall TSynchronizeProgressForm::TSynchronizeProgressForm(TComponent * Owner
 {
   FStarted = false;
   FCanceled = false;
-  FElapsed = EncodeTime(0, 0, 0, 0);
+  FElapsed = EncodeTimeVerbose(0, 0, 0, 0);
   FShowAsModalStorage = NULL;
   FMinimizedByMe = false;
   FCompareOnly = CompareOnly;

+ 5 - 0
putty/SSH.C

@@ -2977,6 +2977,11 @@ static const char *connect_to_host(Ssh ssh, char *host, int port,
 	ssh->savedport = port;
     }
 
+    #ifdef MPEXT
+    // make sure the field is initialized, in case lookup below fails
+    ssh->fullhostname = NULL;
+    #endif
+    
     /*
      * Try to find host.
      */

+ 8 - 8
putty/SSHSH512.C

@@ -13,14 +13,14 @@
  * overlap destination with one source, but the others can't.
  */
 #define add(r,x,y) ( r.lo = y.lo + x.lo, \
-		     r.hi = y.hi + x.hi + (r.lo < y.lo) )
-#define rorB(r,x,y) ( r.lo = (x.hi >> ((y)-32)) | (x.lo << (64-(y))), \
-		      r.hi = (x.lo >> ((y)-32)) | (x.hi << (64-(y))) )
-#define rorL(r,x,y) ( r.lo = (x.lo >> (y)) | (x.hi << (32-(y))), \
-		      r.hi = (x.hi >> (y)) | (x.lo << (32-(y))) )
-#define shrB(r,x,y) ( r.lo = x.hi >> ((y)-32), r.hi = 0 )
-#define shrL(r,x,y) ( r.lo = (x.lo >> (y)) | (x.hi << (32-(y))), \
-		      r.hi = x.hi >> (y) )
+		     r.hi = y.hi + x.hi + ((uint32)r.lo < (uint32)y.lo) )
+#define rorB(r,x,y) ( r.lo = ((uint32)x.hi >> ((y)-32)) | ((uint32)x.lo << (64-(y))), \
+		      r.hi = ((uint32)x.lo >> ((y)-32)) | ((uint32)x.hi << (64-(y))) )
+#define rorL(r,x,y) ( r.lo = ((uint32)x.lo >> (y)) | ((uint32)x.hi << (32-(y))), \
+		      r.hi = ((uint32)x.hi >> (y)) | ((uint32)x.lo << (32-(y))) )
+#define shrB(r,x,y) ( r.lo = (uint32)x.hi >> ((y)-32), r.hi = 0 )
+#define shrL(r,x,y) ( r.lo = ((uint32)x.lo >> (y)) | ((uint32)x.hi << (32-(y))), \
+		      r.hi = (uint32)x.hi >> (y) )
 #define and(r,x,y) ( r.lo = x.lo & y.lo, r.hi = x.hi & y.hi )
 #define xor(r,x,y) ( r.lo = x.lo ^ y.lo, r.hi = x.hi ^ y.hi )
 #define not(r,x) ( r.lo = ~x.lo, r.hi = ~x.hi )

+ 31 - 38
putty/windows/WINGSS.C

@@ -8,37 +8,30 @@
 #include "sshgss.h"
 #include "misc.h"
 
-#define NOTHING
-#define DECL_SSPI_FUNCTION(linkage, rettype, name, params)	\
-  typedef rettype (WINAPI *t_##name) params;			\
-  linkage t_##name p_##name
-#define GET_SSPI_FUNCTION(module, name)					\
-  p_##name = module ? (t_##name) GetProcAddress(module, #name) : NULL
-
-DECL_SSPI_FUNCTION(static, SECURITY_STATUS,
-		   AcquireCredentialsHandleA,
-		   (SEC_CHAR *, SEC_CHAR *, ULONG, PLUID,
-		    PVOID, SEC_GET_KEY_FN, PVOID, PCredHandle, PTimeStamp));
-DECL_SSPI_FUNCTION(static, SECURITY_STATUS,
-		   InitializeSecurityContextA,
-		   (PCredHandle, PCtxtHandle, SEC_CHAR *, ULONG, ULONG,
-		   ULONG, PSecBufferDesc, ULONG, PCtxtHandle,
-		    PSecBufferDesc, PULONG, PTimeStamp));
-DECL_SSPI_FUNCTION(static, SECURITY_STATUS,
-		   FreeContextBuffer,
-		   (PVOID));
-DECL_SSPI_FUNCTION(static, SECURITY_STATUS,
-		   FreeCredentialsHandle,
-		   (PCredHandle));
-DECL_SSPI_FUNCTION(static, SECURITY_STATUS,
-		   DeleteSecurityContext,
-		   (PCtxtHandle));
-DECL_SSPI_FUNCTION(static, SECURITY_STATUS,
-		   QueryContextAttributesA,
-		   (PCtxtHandle, ULONG, PVOID));
-DECL_SSPI_FUNCTION(static, SECURITY_STATUS,
-		   MakeSignature,
-		   (PCtxtHandle, ULONG, PSecBufferDesc, ULONG));
+DECL_WINDOWS_FUNCTION(static, SECURITY_STATUS,
+		      AcquireCredentialsHandleA,
+		      (SEC_CHAR *, SEC_CHAR *, ULONG, PLUID,
+		       PVOID, SEC_GET_KEY_FN, PVOID, PCredHandle, PTimeStamp));
+DECL_WINDOWS_FUNCTION(static, SECURITY_STATUS,
+		      InitializeSecurityContextA,
+		      (PCredHandle, PCtxtHandle, SEC_CHAR *, ULONG, ULONG,
+		       ULONG, PSecBufferDesc, ULONG, PCtxtHandle,
+		       PSecBufferDesc, PULONG, PTimeStamp));
+DECL_WINDOWS_FUNCTION(static, SECURITY_STATUS,
+		      FreeContextBuffer,
+		      (PVOID));
+DECL_WINDOWS_FUNCTION(static, SECURITY_STATUS,
+		      FreeCredentialsHandle,
+		      (PCredHandle));
+DECL_WINDOWS_FUNCTION(static, SECURITY_STATUS,
+		      DeleteSecurityContext,
+		      (PCtxtHandle));
+DECL_WINDOWS_FUNCTION(static, SECURITY_STATUS,
+		      QueryContextAttributesA,
+		      (PCtxtHandle, ULONG, PVOID));
+DECL_WINDOWS_FUNCTION(static, SECURITY_STATUS,
+		      MakeSignature,
+		      (PCtxtHandle, ULONG, PSecBufferDesc, ULONG));
 
 static HMODULE security_module = NULL;
 
@@ -61,13 +54,13 @@ int ssh_gss_init(void)
 
     security_module = LoadLibrary("secur32.dll");
     if (security_module) {
-	GET_SSPI_FUNCTION(security_module, AcquireCredentialsHandleA);
-	GET_SSPI_FUNCTION(security_module, InitializeSecurityContextA);
-	GET_SSPI_FUNCTION(security_module, FreeContextBuffer);
-	GET_SSPI_FUNCTION(security_module, FreeCredentialsHandle);
-	GET_SSPI_FUNCTION(security_module, DeleteSecurityContext);
-	GET_SSPI_FUNCTION(security_module, QueryContextAttributesA);
-	GET_SSPI_FUNCTION(security_module, MakeSignature);
+	GET_WINDOWS_FUNCTION(security_module, AcquireCredentialsHandleA);
+	GET_WINDOWS_FUNCTION(security_module, InitializeSecurityContextA);
+	GET_WINDOWS_FUNCTION(security_module, FreeContextBuffer);
+	GET_WINDOWS_FUNCTION(security_module, FreeCredentialsHandle);
+	GET_WINDOWS_FUNCTION(security_module, DeleteSecurityContext);
+	GET_WINDOWS_FUNCTION(security_module, QueryContextAttributesA);
+	GET_WINDOWS_FUNCTION(security_module, MakeSignature);
 	return 1;
     }
     return 0;

+ 74 - 84
putty/windows/WINNET.C

@@ -148,65 +148,49 @@ static int cmpforsearch(void *av, void *bv)
     return 0;
 }
 
-#define NOTHING
-#define DECL_WINSOCK_FUNCTION(linkage, rettype, name, params) \
-    typedef rettype (WINAPI *t_##name) params; \
-    linkage t_##name p_##name
-#define GET_WINSOCK_FUNCTION(module, name) \
-    p_##name = module ? (t_##name) GetProcAddress(module, #name) : NULL
-
-DECL_WINSOCK_FUNCTION(NOTHING, int, WSAAsyncSelect,
-		      (SOCKET, HWND, u_int, long));
-DECL_WINSOCK_FUNCTION(NOTHING, int, WSAEventSelect, (SOCKET, WSAEVENT, long));
-DECL_WINSOCK_FUNCTION(NOTHING, int, select,
-		      (int, fd_set FAR *, fd_set FAR *,
-		       fd_set FAR *, const struct timeval FAR *));
-DECL_WINSOCK_FUNCTION(NOTHING, int, WSAGetLastError, (void));
-DECL_WINSOCK_FUNCTION(NOTHING, int, WSAEnumNetworkEvents,
-		      (SOCKET, WSAEVENT, LPWSANETWORKEVENTS));
-DECL_WINSOCK_FUNCTION(static, int, WSAStartup, (WORD, LPWSADATA));
-DECL_WINSOCK_FUNCTION(static, int, WSACleanup, (void));
-DECL_WINSOCK_FUNCTION(static, int, closesocket, (SOCKET));
-DECL_WINSOCK_FUNCTION(static, u_long, ntohl, (u_long));
-DECL_WINSOCK_FUNCTION(static, u_long, htonl, (u_long));
-DECL_WINSOCK_FUNCTION(static, u_short, htons, (u_short));
-DECL_WINSOCK_FUNCTION(static, u_short, ntohs, (u_short));
-DECL_WINSOCK_FUNCTION(static, int, gethostname, (char *, int));
-DECL_WINSOCK_FUNCTION(static, struct hostent FAR *, gethostbyname,
+DECL_WINDOWS_FUNCTION(static, int, WSAStartup, (WORD, LPWSADATA));
+DECL_WINDOWS_FUNCTION(static, int, WSACleanup, (void));
+DECL_WINDOWS_FUNCTION(static, int, closesocket, (SOCKET));
+DECL_WINDOWS_FUNCTION(static, u_long, ntohl, (u_long));
+DECL_WINDOWS_FUNCTION(static, u_long, htonl, (u_long));
+DECL_WINDOWS_FUNCTION(static, u_short, htons, (u_short));
+DECL_WINDOWS_FUNCTION(static, u_short, ntohs, (u_short));
+DECL_WINDOWS_FUNCTION(static, int, gethostname, (char *, int));
+DECL_WINDOWS_FUNCTION(static, struct hostent FAR *, gethostbyname,
 		      (const char FAR *));
-DECL_WINSOCK_FUNCTION(static, struct servent FAR *, getservbyname,
+DECL_WINDOWS_FUNCTION(static, struct servent FAR *, getservbyname,
 		      (const char FAR *, const char FAR *));
-DECL_WINSOCK_FUNCTION(static, unsigned long, inet_addr, (const char FAR *));
-DECL_WINSOCK_FUNCTION(static, char FAR *, inet_ntoa, (struct in_addr));
-DECL_WINSOCK_FUNCTION(static, int, connect,
+DECL_WINDOWS_FUNCTION(static, unsigned long, inet_addr, (const char FAR *));
+DECL_WINDOWS_FUNCTION(static, char FAR *, inet_ntoa, (struct in_addr));
+DECL_WINDOWS_FUNCTION(static, int, connect,
 		      (SOCKET, const struct sockaddr FAR *, int));
-DECL_WINSOCK_FUNCTION(static, int, bind,
+DECL_WINDOWS_FUNCTION(static, int, bind,
 		      (SOCKET, const struct sockaddr FAR *, int));
-DECL_WINSOCK_FUNCTION(static, int, setsockopt,
+DECL_WINDOWS_FUNCTION(static, int, setsockopt,
 		      (SOCKET, int, int, const char FAR *, int));
-DECL_WINSOCK_FUNCTION(static, SOCKET, socket, (int, int, int));
-DECL_WINSOCK_FUNCTION(static, int, listen, (SOCKET, int));
-DECL_WINSOCK_FUNCTION(static, int, send, (SOCKET, const char FAR *, int, int));
-DECL_WINSOCK_FUNCTION(static, int, ioctlsocket,
+DECL_WINDOWS_FUNCTION(static, SOCKET, socket, (int, int, int));
+DECL_WINDOWS_FUNCTION(static, int, listen, (SOCKET, int));
+DECL_WINDOWS_FUNCTION(static, int, send, (SOCKET, const char FAR *, int, int));
+DECL_WINDOWS_FUNCTION(static, int, ioctlsocket,
 		      (SOCKET, long, u_long FAR *));
-DECL_WINSOCK_FUNCTION(static, SOCKET, accept,
+DECL_WINDOWS_FUNCTION(static, SOCKET, accept,
 		      (SOCKET, struct sockaddr FAR *, int FAR *));
-DECL_WINSOCK_FUNCTION(static, int, recv, (SOCKET, char FAR *, int, int));
-DECL_WINSOCK_FUNCTION(static, int, WSAIoctl,
+DECL_WINDOWS_FUNCTION(static, int, recv, (SOCKET, char FAR *, int, int));
+DECL_WINDOWS_FUNCTION(static, int, WSAIoctl,
 		      (SOCKET, DWORD, LPVOID, DWORD, LPVOID, DWORD,
 		       LPDWORD, LPWSAOVERLAPPED,
 		       LPWSAOVERLAPPED_COMPLETION_ROUTINE));
 #ifndef NO_IPV6
-DECL_WINSOCK_FUNCTION(static, int, getaddrinfo,
+DECL_WINDOWS_FUNCTION(static, int, getaddrinfo,
 		      (const char *nodename, const char *servname,
 		       const struct addrinfo *hints, struct addrinfo **res));
-DECL_WINSOCK_FUNCTION(static, void, freeaddrinfo, (struct addrinfo *res));
-DECL_WINSOCK_FUNCTION(static, int, getnameinfo,
+DECL_WINDOWS_FUNCTION(static, void, freeaddrinfo, (struct addrinfo *res));
+DECL_WINDOWS_FUNCTION(static, int, getnameinfo,
 		      (const struct sockaddr FAR * sa, socklen_t salen,
 		       char FAR * host, size_t hostlen, char FAR * serv,
 		       size_t servlen, int flags));
-DECL_WINSOCK_FUNCTION(static, char *, gai_strerror, (int ecode));
-DECL_WINSOCK_FUNCTION(static, int, WSAAddressToStringA,
+DECL_WINDOWS_FUNCTION(static, char *, gai_strerror, (int ecode));
+DECL_WINDOWS_FUNCTION(static, int, WSAAddressToStringA,
 		      (LPSOCKADDR, DWORD, LPWSAPROTOCOL_INFO,
 		       LPSTR, LPDWORD));
 #endif
@@ -260,10 +244,10 @@ void sk_init(void)
 #ifdef NET_SETUP_DIAGNOSTICS
 	logevent(NULL, "Native WinSock IPv6 support detected");
 #endif
-	GET_WINSOCK_FUNCTION(winsock_module, getaddrinfo);
-	GET_WINSOCK_FUNCTION(winsock_module, freeaddrinfo);
-	GET_WINSOCK_FUNCTION(winsock_module, getnameinfo);
-	GET_WINSOCK_FUNCTION(winsock_module, gai_strerror);
+	GET_WINDOWS_FUNCTION(winsock_module, getaddrinfo);
+	GET_WINDOWS_FUNCTION(winsock_module, freeaddrinfo);
+	GET_WINDOWS_FUNCTION(winsock_module, getnameinfo);
+	GET_WINDOWS_FUNCTION(winsock_module, gai_strerror);
     } else {
 	/* Fall back to wship6.dll for Windows 2000 */
 	wship6_module = LoadLibrary("wship6.dll");
@@ -271,50 +255,50 @@ void sk_init(void)
 #ifdef NET_SETUP_DIAGNOSTICS
 	    logevent(NULL, "WSH IPv6 support detected");
 #endif
-	    GET_WINSOCK_FUNCTION(wship6_module, getaddrinfo);
-	    GET_WINSOCK_FUNCTION(wship6_module, freeaddrinfo);
-	    GET_WINSOCK_FUNCTION(wship6_module, getnameinfo);
-	    GET_WINSOCK_FUNCTION(wship6_module, gai_strerror);
+	    GET_WINDOWS_FUNCTION(wship6_module, getaddrinfo);
+	    GET_WINDOWS_FUNCTION(wship6_module, freeaddrinfo);
+	    GET_WINDOWS_FUNCTION(wship6_module, getnameinfo);
+	    GET_WINDOWS_FUNCTION(wship6_module, gai_strerror);
 	} else {
 #ifdef NET_SETUP_DIAGNOSTICS
 	    logevent(NULL, "No IPv6 support detected");
 #endif
 	}
     }
-    GET_WINSOCK_FUNCTION(winsock2_module, WSAAddressToStringA);
+    GET_WINDOWS_FUNCTION(winsock2_module, WSAAddressToStringA);
 #else
 #ifdef NET_SETUP_DIAGNOSTICS
     logevent(NULL, "PuTTY was built without IPv6 support");
 #endif
 #endif
 
-    GET_WINSOCK_FUNCTION(winsock_module, WSAAsyncSelect);
-    GET_WINSOCK_FUNCTION(winsock_module, WSAEventSelect);
-    GET_WINSOCK_FUNCTION(winsock_module, select);
-    GET_WINSOCK_FUNCTION(winsock_module, WSAGetLastError);
-    GET_WINSOCK_FUNCTION(winsock_module, WSAEnumNetworkEvents);
-    GET_WINSOCK_FUNCTION(winsock_module, WSAStartup);
-    GET_WINSOCK_FUNCTION(winsock_module, WSACleanup);
-    GET_WINSOCK_FUNCTION(winsock_module, closesocket);
-    GET_WINSOCK_FUNCTION(winsock_module, ntohl);
-    GET_WINSOCK_FUNCTION(winsock_module, htonl);
-    GET_WINSOCK_FUNCTION(winsock_module, htons);
-    GET_WINSOCK_FUNCTION(winsock_module, ntohs);
-    GET_WINSOCK_FUNCTION(winsock_module, gethostname);
-    GET_WINSOCK_FUNCTION(winsock_module, gethostbyname);
-    GET_WINSOCK_FUNCTION(winsock_module, getservbyname);
-    GET_WINSOCK_FUNCTION(winsock_module, inet_addr);
-    GET_WINSOCK_FUNCTION(winsock_module, inet_ntoa);
-    GET_WINSOCK_FUNCTION(winsock_module, connect);
-    GET_WINSOCK_FUNCTION(winsock_module, bind);
-    GET_WINSOCK_FUNCTION(winsock_module, setsockopt);
-    GET_WINSOCK_FUNCTION(winsock_module, socket);
-    GET_WINSOCK_FUNCTION(winsock_module, listen);
-    GET_WINSOCK_FUNCTION(winsock_module, send);
-    GET_WINSOCK_FUNCTION(winsock_module, ioctlsocket);
-    GET_WINSOCK_FUNCTION(winsock_module, accept);
-    GET_WINSOCK_FUNCTION(winsock_module, recv);
-    GET_WINSOCK_FUNCTION(winsock_module, WSAIoctl);
+    GET_WINDOWS_FUNCTION(winsock_module, WSAAsyncSelect);
+    GET_WINDOWS_FUNCTION(winsock_module, WSAEventSelect);
+    GET_WINDOWS_FUNCTION(winsock_module, select);
+    GET_WINDOWS_FUNCTION(winsock_module, WSAGetLastError);
+    GET_WINDOWS_FUNCTION(winsock_module, WSAEnumNetworkEvents);
+    GET_WINDOWS_FUNCTION(winsock_module, WSAStartup);
+    GET_WINDOWS_FUNCTION(winsock_module, WSACleanup);
+    GET_WINDOWS_FUNCTION(winsock_module, closesocket);
+    GET_WINDOWS_FUNCTION(winsock_module, ntohl);
+    GET_WINDOWS_FUNCTION(winsock_module, htonl);
+    GET_WINDOWS_FUNCTION(winsock_module, htons);
+    GET_WINDOWS_FUNCTION(winsock_module, ntohs);
+    GET_WINDOWS_FUNCTION(winsock_module, gethostname);
+    GET_WINDOWS_FUNCTION(winsock_module, gethostbyname);
+    GET_WINDOWS_FUNCTION(winsock_module, getservbyname);
+    GET_WINDOWS_FUNCTION(winsock_module, inet_addr);
+    GET_WINDOWS_FUNCTION(winsock_module, inet_ntoa);
+    GET_WINDOWS_FUNCTION(winsock_module, connect);
+    GET_WINDOWS_FUNCTION(winsock_module, bind);
+    GET_WINDOWS_FUNCTION(winsock_module, setsockopt);
+    GET_WINDOWS_FUNCTION(winsock_module, socket);
+    GET_WINDOWS_FUNCTION(winsock_module, listen);
+    GET_WINDOWS_FUNCTION(winsock_module, send);
+    GET_WINDOWS_FUNCTION(winsock_module, ioctlsocket);
+    GET_WINDOWS_FUNCTION(winsock_module, accept);
+    GET_WINDOWS_FUNCTION(winsock_module, recv);
+    GET_WINDOWS_FUNCTION(winsock_module, WSAIoctl);
 
     /* Try to get the best WinSock version we can get */
     if (!sk_startup(2,2) &&
@@ -588,13 +572,19 @@ void sk_getaddr(SockAddr addr, char *buf, int buflen)
 
 #ifndef NO_IPV6
     if (step.ai) {
+	int err = 0;
 	if (p_WSAAddressToStringA) {
-	    DWORD dwbuflen;
-	    p_WSAAddressToStringA(step.ai->ai_addr, step.ai->ai_addrlen,
-				  NULL, buf, &dwbuflen);
-	    buflen = dwbuflen;
+	    DWORD dwbuflen = buflen;
+	    err = p_WSAAddressToStringA(step.ai->ai_addr, step.ai->ai_addrlen,
+					NULL, buf, &dwbuflen);
 	} else
-	    strncpy(buf, "IPv6", buflen);
+	    err = -1;
+	if (err) {
+	    strncpy(buf, addr->hostname, buflen);
+	    if (!buf[0])
+		strncpy(buf, "<unknown>", buflen);
+	    buf[buflen-1] = '\0';
+	}
     } else
 #endif
     if (SOCKADDR_FAMILY(addr, step) == AF_INET) {

+ 9 - 12
putty/windows/WINSTORE.C

@@ -23,9 +23,8 @@ static const char hex[16] = "0123456789ABCDEF";
 
 static int tried_shgetfolderpath = FALSE;
 static HMODULE shell32_module = NULL;
-typedef HRESULT (WINAPI *p_SHGetFolderPath_t)
-    (HWND, int, HANDLE, DWORD, LPTSTR);
-static p_SHGetFolderPath_t p_SHGetFolderPath = NULL;
+DECL_WINDOWS_FUNCTION(static, HRESULT, SHGetFolderPathA, 
+		      (HWND, int, HANDLE, DWORD, LPSTR));
 
 static void mungestr(const char *in, char *out)
 {
@@ -521,21 +520,19 @@ static HANDLE access_random_seed(int action)
 	 * However, the invocation below requires IE5+ anyway,
 	 * so stuff that. */
 	shell32_module = LoadLibrary("SHELL32.DLL");
-	if (shell32_module) {
-	    p_SHGetFolderPath = (p_SHGetFolderPath_t)
-		GetProcAddress(shell32_module, "SHGetFolderPathA");
-	}
+	GET_WINDOWS_FUNCTION(shell32_module, SHGetFolderPathA);
+	tried_shgetfolderpath = TRUE;
     }
-    if (p_SHGetFolderPath) {
-	if (SUCCEEDED(p_SHGetFolderPath(NULL, CSIDL_LOCAL_APPDATA,
-					NULL, SHGFP_TYPE_CURRENT, seedpath))) {
+    if (p_SHGetFolderPathA) {
+	if (SUCCEEDED(p_SHGetFolderPathA(NULL, CSIDL_LOCAL_APPDATA,
+					 NULL, SHGFP_TYPE_CURRENT, seedpath))) {
 	    strcat(seedpath, "\\PUTTY.RND");
 	    if (try_random_seed(seedpath, action, &rethandle))
 		return rethandle;
 	}
 
-	if (SUCCEEDED(p_SHGetFolderPath(NULL, CSIDL_APPDATA,
-					NULL, SHGFP_TYPE_CURRENT, seedpath))) {
+	if (SUCCEEDED(p_SHGetFolderPathA(NULL, CSIDL_APPDATA,
+					 NULL, SHGFP_TYPE_CURRENT, seedpath))) {
 	    strcat(seedpath, "\\PUTTY.RND");
 	    if (try_random_seed(seedpath, action, &rethandle))
 		return rethandle;

+ 23 - 10
putty/windows/WINSTUFF.H

@@ -75,6 +75,19 @@ struct FontSpec {
 #define BOXRESULT (DLGWINDOWEXTRA + sizeof(LONG_PTR))
 #define DF_END 0x0001
 
+/*
+ * Dynamically linked functions.
+ * This is somewhat circuitous to allow function-renaming macros to be
+ * expanded, principally the ANSI/Unicode DoSomethingA/DoSomethingW.
+ */
+#define DECL_WINDOWS_FUNCTION(linkage, rettype, name, params) \
+    typedef rettype (WINAPI *t_##name) params; \
+    linkage t_##name p_##name
+#define STR1(x) #x
+#define STR(x) STR1(x)
+#define GET_WINDOWS_FUNCTION(module, name) \
+    p_##name = module ? (t_##name) GetProcAddress(module, STR(name)) : NULL
+
 /*
  * Global variables. Most modules declare these `extern', but
  * window.c will do `#define PUTTY_DO_GLOBALS' before including this
@@ -207,16 +220,16 @@ GLOBAL void *logctx;
  * that module must be exported from it as function pointers. So
  * here they are.
  */
-extern int (WINAPI *p_WSAAsyncSelect)
-    (SOCKET s, HWND hWnd, u_int wMsg, long lEvent);
-extern int (WINAPI *p_WSAEventSelect)
-    (SOCKET s, WSAEVENT hEventObject, long lNetworkEvents);
-extern int (WINAPI *p_select)
-    (int nfds, fd_set FAR * readfds, fd_set FAR * writefds,
-     fd_set FAR *exceptfds, const struct timeval FAR * timeout);
-extern int (WINAPI *p_WSAGetLastError)(void);
-extern int (WINAPI *p_WSAEnumNetworkEvents)
-    (SOCKET s, WSAEVENT hEventObject, LPWSANETWORKEVENTS lpNetworkEvents);
+DECL_WINDOWS_FUNCTION(GLOBAL, int, WSAAsyncSelect,
+		      (SOCKET, HWND, u_int, long));
+DECL_WINDOWS_FUNCTION(GLOBAL, int, WSAEventSelect,
+		      (SOCKET, WSAEVENT, long));
+DECL_WINDOWS_FUNCTION(GLOBAL, int, select,
+		      (int, fd_set FAR *, fd_set FAR *,
+		       fd_set FAR *, const struct timeval FAR *));
+DECL_WINDOWS_FUNCTION(GLOBAL, int, WSAGetLastError, (void));
+DECL_WINDOWS_FUNCTION(GLOBAL, int, WSAEnumNetworkEvents,
+		      (SOCKET, WSAEVENT, LPWSANETWORKEVENTS));
 
 extern int socket_writable(SOCKET skt);
 

+ 1 - 1
release/winscp.u3i

@@ -1,6 +1,6 @@
 <?xml version="1.0"?>
 <u3manifest version="1.0">
-  <application uuid="48b341d1-d411-4b5a-a82c-f3b5d65602fc" version="4.2.4">
+  <application uuid="48b341d1-d411-4b5a-a82c-f3b5d65602fc" version="4.2.5">
     <icon>winscp.ico</icon>
     <name>WinSCP</name>
     <description>Freeware SFTP (SSH File Transfer Protocol), FTP (File Transfer Protocol) and SCP (Secure CoPy) client for Windows using SSH (Secure SHell). Its main function is safe copying of files between a local and a remote computer.</description>

+ 1 - 1
resource/TextsCore2.rc

@@ -227,7 +227,7 @@ BEGIN
     "switches:\n"
     "  -delete             Delete source local file(s) after transfer\n"
     "  -resume             Resume transfer if possible (SFTP and FTP protocols only)\n"
-    "  -append             Append file to end of target file (FTP protocol only)\n"
+    "  -append             Append file to end of target file (SFTP protocol only)\n"
     "  -preservetime       Preserve timestamp\n"
     "  -nopreservetime     Do not preserve timestamp\n"
     "  -permissions=<mode> Set permissions\n"

+ 1 - 1
windows/GUIConfiguration.cpp

@@ -498,7 +498,7 @@ TStrings * __fastcall TCopyParamList::GetNameList() const
 
     for (int i = 0; i < Count; i++)
     {
-      FNameList->Add(StripHotkey(FNames->Strings[i]));
+      FNameList->Add(FNames->Strings[i]);
     }
   }
   return FNameList;

+ 5 - 4
windows/Tools.cpp

@@ -9,6 +9,7 @@
 
 #include <Common.h>
 #include <TextsWin.h>
+#include <Exceptions.h>
 
 #include "GUITools.h"
 #include "VCLCommon.h"
@@ -204,7 +205,7 @@ bool __fastcall ExecuteShellAndWait(const AnsiString Command)
     &Application->ProcessMessages);
 }
 //---------------------------------------------------------------------------
-void __fastcall CreateDesktopShortCut(const AnsiString &Name,
+void __fastcall CreateDesktopShortCut(const AnsiString & Name,
   const AnsiString &File, const AnsiString & Params, const AnsiString & Description,
   int SpecialFolder)
 {
@@ -268,7 +269,7 @@ void __fastcall CreateDesktopShortCut(const AnsiString &Name,
               strShortCutLocation += AnsiString("\\") + Name + ".lnk";
               if (!SUCCEEDED(pPersistFile->Save(strShortCutLocation.c_bstr(), TRUE)))
               {
-                throw Exception("");
+                RaiseLastOSError();
               }
             }
             __finally
@@ -285,9 +286,9 @@ void __fastcall CreateDesktopShortCut(const AnsiString &Name,
       CoUninitialize();
     }
   }
-  catch(...)
+  catch(Exception & E)
   {
-    throw Exception(CREATE_SHORTCUT_ERROR);
+    throw ExtException(&E, LoadStr(CREATE_SHORTCUT_ERROR));
   }
 }
 //---------------------------------------------------------------------------

+ 8 - 5
windows/WinConfiguration.cpp

@@ -1088,10 +1088,13 @@ AnsiString __fastcall TWinConfiguration::StronglyRecryptPassword(AnsiString Pass
   else
   {
     Password = TCustomWinConfiguration::DecryptPassword(Password, Key);
-    assert(!FPlainMasterPasswordEncrypt.IsEmpty());
-    ScramblePassword(Password);
-    AES256EncyptWithMAC(Password, FPlainMasterPasswordEncrypt, Result);
-    Result = SetExternalEncryptedPassword(Result);
+    if (!Password.IsEmpty())
+    {
+      assert(!FPlainMasterPasswordEncrypt.IsEmpty());
+      ScramblePassword(Password);
+      AES256EncyptWithMAC(Password, FPlainMasterPasswordEncrypt, Result);
+      Result = SetExternalEncryptedPassword(Result);
+    }
   }
   return Result;
 }
@@ -1176,7 +1179,7 @@ void __fastcall TWinConfiguration::ClearMasterPassword()
 //---------------------------------------------------------------------------
 void __fastcall TWinConfiguration::AskForMasterPasswordIfNotSet()
 {
-  if (FUseMasterPassword && FPlainMasterPasswordEncrypt.IsEmpty())
+  if (FPlainMasterPasswordEncrypt.IsEmpty())
   {
     assert(FOnMasterPasswordPrompt != NULL);
     FOnMasterPasswordPrompt();

+ 1 - 1
windows/WinInterface.cpp

@@ -548,7 +548,7 @@ int __fastcall ExceptionMessageDialog(Exception * E, TQueryType Type,
     }
   }
   AnsiString Message;
-  // this is always called form within ExceptionMessage check,
+  // this is always called from within ExceptionMessage check,
   // so it should never fail here
   CHECK(ExceptionMessage(E, Message));