Browse Source

Refactoring file iteration

Source commit: e7c3822390daa5727d75fc5b36c82c8c1243bfea
Martin Prikryl 7 years ago
parent
commit
2ab220f319

+ 23 - 14
source/core/Common.cpp

@@ -1324,6 +1324,20 @@ bool __fastcall IsHex(wchar_t Ch)
     ((Ch >= 'a') && (Ch <= 'f'));
     ((Ch >= 'a') && (Ch <= 'f'));
 }
 }
 //---------------------------------------------------------------------------
 //---------------------------------------------------------------------------
+TSearchRecOwned::~TSearchRecOwned()
+{
+  if (Opened)
+  {
+    FindClose(*this);
+  }
+}
+//---------------------------------------------------------------------------
+void TSearchRecOwned::Close()
+{
+  FindClose(*this);
+  Opened = false;
+}
+//---------------------------------------------------------------------------
 int __fastcall FindCheck(int Result, const UnicodeString & Path)
 int __fastcall FindCheck(int Result, const UnicodeString & Path)
 {
 {
   if ((Result != ERROR_SUCCESS) &&
   if ((Result != ERROR_SUCCESS) &&
@@ -1338,7 +1352,9 @@ int __fastcall FindCheck(int Result, const UnicodeString & Path)
 int __fastcall FindFirstUnchecked(const UnicodeString & Path, int Attr, TSearchRecChecked & F)
 int __fastcall FindFirstUnchecked(const UnicodeString & Path, int Attr, TSearchRecChecked & F)
 {
 {
   F.Path = Path;
   F.Path = Path;
-  return FindFirst(ApiPath(Path), Attr, F);
+  int Result = FindFirst(ApiPath(Path), Attr, F);
+  F.Opened = (Result == 0);
+  return Result;
 }
 }
 //---------------------------------------------------------------------------
 //---------------------------------------------------------------------------
 int __fastcall FindFirstChecked(const UnicodeString & Path, int Attr, TSearchRecChecked & F)
 int __fastcall FindFirstChecked(const UnicodeString & Path, int Attr, TSearchRecChecked & F)
@@ -1381,26 +1397,19 @@ void __fastcall ProcessLocalDirectory(UnicodeString DirName,
   {
   {
     FindAttrs = faReadOnly | faHidden | faSysFile | faDirectory | faArchive;
     FindAttrs = faReadOnly | faHidden | faSysFile | faDirectory | faArchive;
   }
   }
-  TSearchRecChecked SearchRec;
 
 
   DirName = IncludeTrailingBackslash(DirName);
   DirName = IncludeTrailingBackslash(DirName);
+  TSearchRecOwned SearchRec;
   if (FindFirstChecked(DirName + L"*.*", FindAttrs, SearchRec) == 0)
   if (FindFirstChecked(DirName + L"*.*", FindAttrs, SearchRec) == 0)
   {
   {
-    try
+    do
     {
     {
-      do
+      if ((SearchRec.Name != L".") && (SearchRec.Name != L".."))
       {
       {
-        if ((SearchRec.Name != L".") && (SearchRec.Name != L".."))
-        {
-          CallBackFunc(DirName + SearchRec.Name, SearchRec, Param);
-        }
+        CallBackFunc(DirName + SearchRec.Name, SearchRec, Param);
+      }
 
 
-      } while (FindNextChecked(SearchRec) == 0);
-    }
-    __finally
-    {
-      FindClose(SearchRec);
-    }
+    } while (FindNextChecked(SearchRec) == 0);
   }
   }
 }
 }
 //---------------------------------------------------------------------------
 //---------------------------------------------------------------------------

+ 6 - 0
source/core/Common.h

@@ -178,6 +178,12 @@ bool __fastcall FileSearchRec(const UnicodeString FileName, TSearchRec & Rec);
 struct TSearchRecChecked : public TSearchRec
 struct TSearchRecChecked : public TSearchRec
 {
 {
   UnicodeString Path;
   UnicodeString Path;
+  bool Opened;
+};
+struct TSearchRecOwned : public TSearchRecChecked
+{
+  ~TSearchRecOwned();
+  void Close();
 };
 };
 int __fastcall FindCheck(int Result, const UnicodeString & Path);
 int __fastcall FindCheck(int Result, const UnicodeString & Path);
 int __fastcall FindFirstUnchecked(const UnicodeString & Path, int Attr, TSearchRecChecked & F);
 int __fastcall FindFirstUnchecked(const UnicodeString & Path, int Attr, TSearchRecChecked & F);

+ 32 - 50
source/core/ScpFileSystem.cpp

@@ -1996,69 +1996,51 @@ void __fastcall TSCPFileSystem::SCPDirectorySource(const UnicodeString Directory
 
 
   try
   try
   {
   {
-    int FindAttrs = faReadOnly | faHidden | faSysFile | faDirectory | faArchive;
-    TSearchRecChecked SearchRec;
-    bool FindOK;
+    TSearchRecOwned SearchRec;
+    bool FindOK = FTerminal->LocalFindFirstLoop(IncludeTrailingBackslash(DirectoryName), SearchRec);
 
 
-    FILE_OPERATION_LOOP_BEGIN
+    while (FindOK && !OperationProgress->Cancel)
     {
     {
-      FindOK =
-        (FindFirstChecked(IncludeTrailingBackslash(DirectoryName) + L"*.*",
-           FindAttrs, SearchRec) == 0);
-    }
-    FILE_OPERATION_LOOP_END(FMTLOAD(LIST_DIR_ERROR, (DirectoryName)));
-
-    try
-    {
-      while (FindOK && !OperationProgress->Cancel)
+      UnicodeString FileName = IncludeTrailingBackslash(DirectoryName) + SearchRec.Name;
+      try
       {
       {
-        UnicodeString FileName = IncludeTrailingBackslash(DirectoryName) + SearchRec.Name;
-        try
+        if ((SearchRec.Name != L".") && (SearchRec.Name != L".."))
         {
         {
-          if ((SearchRec.Name != L".") && (SearchRec.Name != L".."))
-          {
-            SCPSource(FileName, TargetDirFull, CopyParam, Params, OperationProgress, Level + 1);
-          }
+          SCPSource(FileName, TargetDirFull, CopyParam, Params, OperationProgress, Level + 1);
         }
         }
-        // Previously we caught ESkipFile, making error being displayed
-        // even when file was excluded by mask. Now the ESkipFile is special
-        // case without error message.
-        catch (EScpFileSkipped &E)
-        {
-          TQueryParams Params(qpAllowContinueOnError);
-          TSuspendFileOperationProgress Suspend(OperationProgress);
+      }
+      // Previously we caught ESkipFile, making error being displayed
+      // even when file was excluded by mask. Now the ESkipFile is special
+      // case without error message.
+      catch (EScpFileSkipped &E)
+      {
+        TQueryParams Params(qpAllowContinueOnError);
+        TSuspendFileOperationProgress Suspend(OperationProgress);
 
 
-          if (FTerminal->QueryUserException(FMTLOAD(COPY_ERROR, (FileName)), &E,
-                qaOK | qaAbort, &Params, qtError) == qaAbort)
-          {
-            OperationProgress->SetCancel(csCancel);
-          }
-          if (!FTerminal->HandleException(&E))
-          {
-            throw;
-          }
+        if (FTerminal->QueryUserException(FMTLOAD(COPY_ERROR, (FileName)), &E,
+              qaOK | qaAbort, &Params, qtError) == qaAbort)
+        {
+          OperationProgress->SetCancel(csCancel);
         }
         }
-        catch (ESkipFile &E)
+        if (!FTerminal->HandleException(&E))
         {
         {
-          // If ESkipFile occurs, just log it and continue with next file
-          TSuspendFileOperationProgress Suspend(OperationProgress);
-          if (!FTerminal->HandleException(&E))
-          {
-            throw;
-          }
+          throw;
         }
         }
-
-        FILE_OPERATION_LOOP_BEGIN
+      }
+      catch (ESkipFile &E)
+      {
+        // If ESkipFile occurs, just log it and continue with next file
+        TSuspendFileOperationProgress Suspend(OperationProgress);
+        if (!FTerminal->HandleException(&E))
         {
         {
-          FindOK = (FindNextChecked(SearchRec) == 0);
+          throw;
         }
         }
-        FILE_OPERATION_LOOP_END(FMTLOAD(LIST_DIR_ERROR, (DirectoryName)));
       }
       }
+
+      FindOK = FTerminal->LocalFindNextLoop(SearchRec);
     }
     }
-    __finally
-    {
-      FindClose(SearchRec);
-    }
+
+    SearchRec.Close();
 
 
     /* TODO : Delete also read-only directories. */
     /* TODO : Delete also read-only directories. */
     /* TODO : Show error message on failure. */
     /* TODO : Show error message on failure. */

+ 40 - 54
source/core/Script.cpp

@@ -736,35 +736,28 @@ TStrings * __fastcall TScript::CreateLocalFileList(TScriptProcParams * Parameter
 
 
       if (FLAGSET(ListType, fltMask))
       if (FLAGSET(ListType, fltMask))
       {
       {
-        TSearchRecChecked SearchRec;
+        TSearchRecOwned SearchRec;
         int FindAttrs = faReadOnly | faHidden | faSysFile | faDirectory | faArchive;
         int FindAttrs = faReadOnly | faHidden | faSysFile | faDirectory | faArchive;
         UnicodeString Error;
         UnicodeString Error;
         bool AnyFound = false;
         bool AnyFound = false;
         if (FindFirstUnchecked(FileName, FindAttrs, SearchRec) == 0)
         if (FindFirstUnchecked(FileName, FindAttrs, SearchRec) == 0)
         {
         {
           UnicodeString Directory = ExtractFilePath(FileName);
           UnicodeString Directory = ExtractFilePath(FileName);
-          try
+          do
           {
           {
-            do
+            if ((SearchRec.Name != L".") && (SearchRec.Name != L".."))
             {
             {
-              if ((SearchRec.Name != L".") && (SearchRec.Name != L".."))
+              UnicodeString FileName = Directory + SearchRec.Name;
+              Result->Add(FileName);
+              if (SearchRec.TimeStamp > LatestModification)
               {
               {
-                UnicodeString FileName = Directory + SearchRec.Name;
-                Result->Add(FileName);
-                if (SearchRec.TimeStamp > LatestModification)
-                {
-                  LatestFileName = FileName;
-                  LatestModification = SearchRec.TimeStamp;
-                }
-                AnyFound = true;
+                LatestFileName = FileName;
+                LatestModification = SearchRec.TimeStamp;
               }
               }
+              AnyFound = true;
             }
             }
-            while (FindNextChecked(SearchRec) == 0);
-          }
-          __finally
-          {
-            FindClose(SearchRec);
           }
           }
+          while (FindNextChecked(SearchRec) == 0);
         }
         }
         else
         else
         {
         {
@@ -2878,7 +2871,7 @@ void __fastcall TManagementScript::LLsProc(TScriptProcParams * Parameters)
     Mask = L"*.*";
     Mask = L"*.*";
   }
   }
 
 
-  TSearchRecChecked SearchRec;
+  TSearchRecOwned SearchRec;
   int FindAttrs = faReadOnly | faHidden | faSysFile | faDirectory | faArchive;
   int FindAttrs = faReadOnly | faHidden | faSysFile | faDirectory | faArchive;
   if (FindFirstUnchecked(IncludeTrailingBackslash(Directory) + Mask, FindAttrs, SearchRec) != 0)
   if (FindFirstUnchecked(IncludeTrailingBackslash(Directory) + Mask, FindAttrs, SearchRec) != 0)
   {
   {
@@ -2886,52 +2879,45 @@ void __fastcall TManagementScript::LLsProc(TScriptProcParams * Parameters)
   }
   }
   else
   else
   {
   {
-    try
-    {
-      UnicodeString TimeFormat = FixedLenDateTimeFormat(FormatSettings.ShortTimeFormat);
-      UnicodeString DateFormat = FixedLenDateTimeFormat(FormatSettings.ShortDateFormat);
-      int DateLen = 0;
-      int TimeLen = 0;
-      bool First = true;
+    UnicodeString TimeFormat = FixedLenDateTimeFormat(FormatSettings.ShortTimeFormat);
+    UnicodeString DateFormat = FixedLenDateTimeFormat(FormatSettings.ShortDateFormat);
+    int DateLen = 0;
+    int TimeLen = 0;
+    bool First = true;
 
 
-      do
+    do
+    {
+      if (SearchRec.Name != L".")
       {
       {
-        if (SearchRec.Name != L".")
+        TDateTime DateTime = FileTimeToDateTime(SearchRec.FindData.ftLastWriteTime);
+        UnicodeString TimeStr = FormatDateTime(TimeFormat, DateTime);
+        UnicodeString DateStr = FormatDateTime(DateFormat, DateTime);
+        if (First)
         {
         {
-          TDateTime DateTime = FileTimeToDateTime(SearchRec.FindData.ftLastWriteTime);
-          UnicodeString TimeStr = FormatDateTime(TimeFormat, DateTime);
-          UnicodeString DateStr = FormatDateTime(DateFormat, DateTime);
-          if (First)
-          {
-            if (TimeLen < TimeStr.Length())
-            {
-              TimeLen = TimeStr.Length();
-            }
-            if (DateLen < DateStr.Length())
-            {
-              DateLen = DateStr.Length();
-            }
-            First = false;
-          }
-          UnicodeString SizeStr;
-          if (FLAGSET(SearchRec.Attr, faDirectory))
+          if (TimeLen < TimeStr.Length())
           {
           {
-            SizeStr = L"<DIR>";
+            TimeLen = TimeStr.Length();
           }
           }
-          else
+          if (DateLen < DateStr.Length())
           {
           {
-            SizeStr = FORMAT(L"%14.0n", (double(SearchRec.Size)));
+            DateLen = DateStr.Length();
           }
           }
-          PrintLine(FORMAT(L"%-*s  %-*s    %-14s %s", (
-            DateLen, DateStr, TimeLen, TimeStr, SizeStr, SearchRec.Name)));
+          First = false;
         }
         }
+        UnicodeString SizeStr;
+        if (FLAGSET(SearchRec.Attr, faDirectory))
+        {
+          SizeStr = L"<DIR>";
+        }
+        else
+        {
+          SizeStr = FORMAT(L"%14.0n", (double(SearchRec.Size)));
+        }
+        PrintLine(FORMAT(L"%-*s  %-*s    %-14s %s", (
+          DateLen, DateStr, TimeLen, TimeStr, SizeStr, SearchRec.Name)));
       }
       }
-      while (FindNextChecked(SearchRec) == 0);
-    }
-    __finally
-    {
-      FindClose(SearchRec);
     }
     }
+    while (FindNextChecked(SearchRec) == 0);
   }
   }
 }
 }
 //---------------------------------------------------------------------------
 //---------------------------------------------------------------------------

+ 97 - 112
source/core/Terminal.cpp

@@ -5479,6 +5479,29 @@ UnicodeString __fastcall TTerminal::SynchronizeParamsStr(int Params)
   return ParamsStr;
   return ParamsStr;
 }
 }
 //---------------------------------------------------------------------------
 //---------------------------------------------------------------------------
+bool __fastcall TTerminal::LocalFindFirstLoop(const UnicodeString & Directory, TSearchRecChecked & SearchRec)
+{
+  bool Result;
+  FILE_OPERATION_LOOP_BEGIN
+  {
+    const int FindAttrs = faReadOnly | faHidden | faSysFile | faDirectory | faArchive;
+    Result = (FindFirstChecked(Directory + L"*.*", FindAttrs, SearchRec) == 0);
+  }
+  FILE_OPERATION_LOOP_END(FMTLOAD(LIST_DIR_ERROR, (ExcludeTrailingBackslash(Directory))));
+  return Result;
+}
+//---------------------------------------------------------------------------
+bool __fastcall TTerminal::LocalFindNextLoop(TSearchRecChecked & SearchRec)
+{
+  bool Result;
+  FILE_OPERATION_LOOP_BEGIN
+  {
+    Result = (FindNextChecked(SearchRec) == 0);
+  }
+  FILE_OPERATION_LOOP_END(FMTLOAD(LIST_DIR_ERROR, (SearchRec.Path)));
+  return Result;
+}
+//---------------------------------------------------------------------------
 void __fastcall TTerminal::DoSynchronizeCollectDirectory(const UnicodeString LocalDirectory,
 void __fastcall TTerminal::DoSynchronizeCollectDirectory(const UnicodeString LocalDirectory,
   const UnicodeString RemoteDirectory, TSynchronizeMode Mode,
   const UnicodeString RemoteDirectory, TSynchronizeMode Mode,
   const TCopyParamType * CopyParam, int Params,
   const TCopyParamType * CopyParam, int Params,
@@ -5509,87 +5532,67 @@ void __fastcall TTerminal::DoSynchronizeCollectDirectory(const UnicodeString Loc
 
 
   try
   try
   {
   {
-    bool Found;
-    TSearchRecChecked SearchRec;
     Data.LocalFileList = CreateSortedStringList();
     Data.LocalFileList = CreateSortedStringList();
 
 
-    FILE_OPERATION_LOOP_BEGIN
-    {
-      int FindAttrs = faReadOnly | faHidden | faSysFile | faDirectory | faArchive;
-      Found = (FindFirstChecked(Data.LocalDirectory + L"*.*", FindAttrs, SearchRec) == 0);
-    }
-    FILE_OPERATION_LOOP_END(FMTLOAD(LIST_DIR_ERROR, (LocalDirectory)));
-
-    if (Found)
+    TSearchRecOwned SearchRec;
+    if (LocalFindFirstLoop(Data.LocalDirectory, SearchRec))
     {
     {
-      try
+      do
       {
       {
-        UnicodeString FileName;
-        while (Found)
+        UnicodeString FileName = SearchRec.Name;
+        // SearchRec.Size in C++B2010 is __int64,
+        // so we should be able to use it instead of FindData.nFileSize*
+        __int64 Size =
+          (static_cast<__int64>(SearchRec.FindData.nFileSizeHigh) << 32) +
+          SearchRec.FindData.nFileSizeLow;
+        TDateTime Modification = FileTimeToDateTime(SearchRec.FindData.ftLastWriteTime);
+        TFileMasks::TParams MaskParams;
+        MaskParams.Size = Size;
+        MaskParams.Modification = Modification;
+        bool Hidden = FLAGSET(SearchRec.Attr, faHidden);
+        UnicodeString RemoteFileName =
+          ChangeFileName(CopyParam, FileName, osLocal, false);
+        UnicodeString FullLocalFileName = Data.LocalDirectory + FileName;
+        UnicodeString BaseFileName = GetBaseFileName(FullLocalFileName);
+        if ((FileName != L".") && (FileName != L"..") &&
+            CopyParam->AllowTransfer(BaseFileName, osLocal, FLAGSET(SearchRec.Attr, faDirectory), MaskParams, Hidden) &&
+            !FFileSystem->TemporaryTransferFile(FileName) &&
+            (FLAGCLEAR(Flags, sfFirstLevel) ||
+             (Options == NULL) ||
+             Options->MatchesFilter(FileName) ||
+             Options->MatchesFilter(RemoteFileName)))
         {
         {
-          FileName = SearchRec.Name;
-          // SearchRec.Size in C++B2010 is __int64,
-          // so we should be able to use it instead of FindData.nFileSize*
-          __int64 Size =
-            (static_cast<__int64>(SearchRec.FindData.nFileSizeHigh) << 32) +
-            SearchRec.FindData.nFileSizeLow;
-          TDateTime Modification = FileTimeToDateTime(SearchRec.FindData.ftLastWriteTime);
-          TFileMasks::TParams MaskParams;
-          MaskParams.Size = Size;
-          MaskParams.Modification = Modification;
-          bool Hidden = FLAGSET(SearchRec.Attr, faHidden);
-          UnicodeString RemoteFileName =
-            ChangeFileName(CopyParam, FileName, osLocal, false);
-          UnicodeString FullLocalFileName = Data.LocalDirectory + FileName;
-          UnicodeString BaseFileName = GetBaseFileName(FullLocalFileName);
-          if ((FileName != L".") && (FileName != L"..") &&
-              CopyParam->AllowTransfer(BaseFileName, osLocal,
-                FLAGSET(SearchRec.Attr, faDirectory), MaskParams, Hidden) &&
-              !FFileSystem->TemporaryTransferFile(FileName) &&
-              (FLAGCLEAR(Flags, sfFirstLevel) ||
-               (Options == NULL) ||
-               Options->MatchesFilter(FileName) ||
-               Options->MatchesFilter(RemoteFileName)))
+          TSynchronizeFileData * FileData = new TSynchronizeFileData;
+
+          FileData->IsDirectory = FLAGSET(SearchRec.Attr, faDirectory);
+          FileData->Info.FileName = FileName;
+          FileData->Info.Directory = Data.LocalDirectory;
+          FileData->Info.Modification = Modification;
+          FileData->Info.ModificationFmt = mfFull;
+          FileData->Info.Size = Size;
+          FileData->LocalLastWriteTime = SearchRec.FindData.ftLastWriteTime;
+          FileData->New = true;
+          FileData->Modified = false;
+          Data.LocalFileList->AddObject(FileName, reinterpret_cast<TObject*>(FileData));
+          if (Configuration->ActualLogProtocol >= 0)
           {
           {
-            TSynchronizeFileData * FileData = new TSynchronizeFileData;
-
-            FileData->IsDirectory = FLAGSET(SearchRec.Attr, faDirectory);
-            FileData->Info.FileName = FileName;
-            FileData->Info.Directory = Data.LocalDirectory;
-            FileData->Info.Modification = Modification;
-            FileData->Info.ModificationFmt = mfFull;
-            FileData->Info.Size = Size;
-            FileData->LocalLastWriteTime = SearchRec.FindData.ftLastWriteTime;
-            FileData->New = true;
-            FileData->Modified = false;
-            Data.LocalFileList->AddObject(FileName,
-              reinterpret_cast<TObject*>(FileData));
-            if (Configuration->ActualLogProtocol >= 0)
-            {
-              LogEvent(FORMAT(L"Local file %s included to synchronization",
-                (FormatFileDetailsForLog(FullLocalFileName, Modification, Size))));
-            }
+            LogEvent(FORMAT(L"Local file %s included to synchronization",
+              (FormatFileDetailsForLog(FullLocalFileName, Modification, Size))));
           }
           }
-          else
-          {
-            if (Configuration->ActualLogProtocol >= 0)
-            {
-              LogEvent(FORMAT(L"Local file %s excluded from synchronization",
-                (FormatFileDetailsForLog(FullLocalFileName, Modification, Size))));
-            }
-          }
-
-          FILE_OPERATION_LOOP_BEGIN
+        }
+        else
+        {
+          if (Configuration->ActualLogProtocol >= 0)
           {
           {
-            Found = (FindNextChecked(SearchRec) == 0);
+            LogEvent(FORMAT(L"Local file %s excluded from synchronization",
+              (FormatFileDetailsForLog(FullLocalFileName, Modification, Size))));
           }
           }
-          FILE_OPERATION_LOOP_END(FMTLOAD(LIST_DIR_ERROR, (LocalDirectory)));
         }
         }
+
       }
       }
-      __finally
-      {
-        FindClose(SearchRec);
-      }
+      while (LocalFindNextLoop(SearchRec));
+
+      SearchRec.Close();
 
 
       // can we expect that ProcessDirectory would take so little time
       // can we expect that ProcessDirectory would take so little time
       // that we can postpone showing progress window until anything actually happens?
       // that we can postpone showing progress window until anything actually happens?
@@ -6793,56 +6796,38 @@ void __fastcall TTerminal::DirectorySource(
 
 
   if (FLAGCLEAR(Params, cpNoRecurse))
   if (FLAGCLEAR(Params, cpNoRecurse))
   {
   {
-    int FindAttrs = faReadOnly | faHidden | faSysFile | faDirectory | faArchive;
-    TSearchRecChecked SearchRec;
-    bool FindOK;
-
-    FILE_OPERATION_LOOP_BEGIN
+    TSearchRecOwned SearchRec;
+    bool FindOK = LocalFindFirstLoop(DirectoryName, SearchRec);
+    while (FindOK && !OperationProgress->Cancel)
     {
     {
-      FindOK =
-        (FindFirstChecked(DirectoryName + L"*.*", FindAttrs, SearchRec) == 0);
-    }
-    FILE_OPERATION_LOOP_END(FMTLOAD(LIST_DIR_ERROR, (DirectoryName)));
-
-    try
-    {
-      while (FindOK && !OperationProgress->Cancel)
+      UnicodeString FileName = DirectoryName + SearchRec.Name;
+      try
       {
       {
-        UnicodeString FileName = DirectoryName + SearchRec.Name;
-        try
-        {
-          if ((SearchRec.Name != L".") && (SearchRec.Name != L".."))
-          {
-            SourceRobust(FileName, DestFullName, CopyParam, Params, OperationProgress, (Flags & ~(tfFirstLevel | tfAutoResume)));
-            // FTP: if any file got uploaded (i.e. there were any file in the directory and at least one was not skipped),
-            // do not try to create the directory, as it should be already created by FZAPI during upload
-            PostCreateDir = false;
-          }
-        }
-        catch (ESkipFile &E)
+        if ((SearchRec.Name != L".") && (SearchRec.Name != L".."))
         {
         {
-          // If ESkipFile occurs, just log it and continue with next file
-          TSuspendFileOperationProgress Suspend(OperationProgress);
-          // here a message to user was displayed, which was not appropriate
-          // when user refused to overwrite the file in subdirectory.
-          // hopefully it won't be missing in other situations.
-          if (!HandleException(&E))
-          {
-            throw;
-          }
+          SourceRobust(FileName, DestFullName, CopyParam, Params, OperationProgress, (Flags & ~(tfFirstLevel | tfAutoResume)));
+          // FTP: if any file got uploaded (i.e. there were any file in the directory and at least one was not skipped),
+          // do not try to create the directory, as it should be already created by FZAPI during upload
+          PostCreateDir = false;
         }
         }
-
-        FILE_OPERATION_LOOP_BEGIN
+      }
+      catch (ESkipFile &E)
+      {
+        // If ESkipFile occurs, just log it and continue with next file
+        TSuspendFileOperationProgress Suspend(OperationProgress);
+        // here a message to user was displayed, which was not appropriate
+        // when user refused to overwrite the file in subdirectory.
+        // hopefully it won't be missing in other situations.
+        if (!HandleException(&E))
         {
         {
-          FindOK = (FindNextChecked(SearchRec) == 0);
+          throw;
         }
         }
-        FILE_OPERATION_LOOP_END(FMTLOAD(LIST_DIR_ERROR, (DirectoryName)));
       }
       }
+
+      FindOK = LocalFindNextLoop(SearchRec);
     }
     }
-    __finally
-    {
-      FindClose(SearchRec);
-    }
+
+    SearchRec.Close();
 
 
     // FTP
     // FTP
     if (PostCreateDir)
     if (PostCreateDir)

+ 2 - 0
source/core/Terminal.h

@@ -333,6 +333,8 @@ protected:
     const TCopyParamType * CopyParam, int Params,
     const TCopyParamType * CopyParam, int Params,
     TSynchronizeDirectory OnSynchronizeDirectory,
     TSynchronizeDirectory OnSynchronizeDirectory,
     TSynchronizeOptions * Options, int Level, TSynchronizeChecklist * Checklist);
     TSynchronizeOptions * Options, int Level, TSynchronizeChecklist * Checklist);
+  bool __fastcall LocalFindFirstLoop(const UnicodeString & Directory, TSearchRecChecked & SearchRec);
+  bool __fastcall LocalFindNextLoop(TSearchRecChecked & SearchRec);
   void __fastcall DoSynchronizeCollectFile(const UnicodeString FileName,
   void __fastcall DoSynchronizeCollectFile(const UnicodeString FileName,
     const TRemoteFile * File, /*TSynchronizeData*/ void * Param);
     const TRemoteFile * File, /*TSynchronizeData*/ void * Param);
   void __fastcall SynchronizeCollectFile(const UnicodeString FileName,
   void __fastcall SynchronizeCollectFile(const UnicodeString FileName,

+ 12 - 22
source/windows/GUIConfiguration.cpp

@@ -1082,31 +1082,21 @@ void __fastcall TGUIConfiguration::SetResourceModule(HINSTANCE Instance)
 void __fastcall TGUIConfiguration::FindLocales(const UnicodeString & LocalesMask, TStrings * Exts, UnicodeString & LocalesExts)
 void __fastcall TGUIConfiguration::FindLocales(const UnicodeString & LocalesMask, TStrings * Exts, UnicodeString & LocalesExts)
 {
 {
   int FindAttrs = faReadOnly | faArchive;
   int FindAttrs = faReadOnly | faArchive;
-  TSearchRecChecked SearchRec;
-  bool Found;
 
 
-  Found =
-    (FindFirstUnchecked(LocalesMask, FindAttrs, SearchRec) == 0);
-  try
-  {
-    UnicodeString Ext;
-    while (Found)
+  TSearchRecOwned SearchRec;
+  bool Found = (FindFirstUnchecked(LocalesMask, FindAttrs, SearchRec) == 0);
+  while (Found)
+  {
+    UnicodeString Ext = ExtractFileExt(SearchRec.Name).UpperCase();
+    // DLL is a remnant from times the .NET assembly was winscp.dll, not winscpnet.dll
+    if ((Ext.Length() >= 3) && (Ext != L".EXE") && (Ext != L".COM") &&
+        (Ext != L".DLL") && (Ext != L".INI") && (Ext != L".MAP"))
     {
     {
-      Ext = ExtractFileExt(SearchRec.Name).UpperCase();
-      // DLL is a remnant from times the .NET assembly was winscp.dll, not winscpnet.dll
-      if ((Ext.Length() >= 3) && (Ext != L".EXE") && (Ext != L".COM") &&
-          (Ext != L".DLL") && (Ext != L".INI") && (Ext != L".MAP"))
-      {
-        Ext = Ext.SubString(2, Ext.Length() - 1);
-        LocalesExts += Ext;
-        Exts->Add(Ext);
-      }
-      Found = (FindNextChecked(SearchRec) == 0);
+      Ext = Ext.SubString(2, Ext.Length() - 1);
+      LocalesExts += Ext;
+      Exts->Add(Ext);
     }
     }
-  }
-  __finally
-  {
-    FindClose(SearchRec);
+    Found = (FindNextChecked(SearchRec) == 0);
   }
   }
 }
 }
 //---------------------------------------------------------------------------
 //---------------------------------------------------------------------------

+ 2 - 2
source/windows/GUITools.cpp

@@ -458,7 +458,7 @@ UnicodeString __fastcall UniqTempDir(const UnicodeString BaseDir, const UnicodeS
 //---------------------------------------------------------------------------
 //---------------------------------------------------------------------------
 bool __fastcall DeleteDirectory(const UnicodeString DirName)
 bool __fastcall DeleteDirectory(const UnicodeString DirName)
 {
 {
-  TSearchRecChecked sr;
+  TSearchRecOwned sr;
   bool retval = true;
   bool retval = true;
   if (FindFirstUnchecked(DirName + L"\\*", faAnyFile, sr) == 0) // VCL Function
   if (FindFirstUnchecked(DirName + L"\\*", faAnyFile, sr) == 0) // VCL Function
   {
   {
@@ -490,7 +490,7 @@ bool __fastcall DeleteDirectory(const UnicodeString DirName)
       }
       }
     }
     }
   }
   }
-  FindClose(sr);
+  sr.Close();
   if (retval) retval = RemoveDir(ApiPath(DirName)); // VCL function
   if (retval) retval = RemoveDir(ApiPath(DirName)); // VCL function
   return retval;
   return retval;
 }
 }

+ 21 - 28
source/windows/WinConfiguration.cpp

@@ -1210,46 +1210,39 @@ void __fastcall TWinConfiguration::LoadFrom(THierarchicalStorage * Storage)
 void __fastcall TWinConfiguration::DoLoadExtensionList(
 void __fastcall TWinConfiguration::DoLoadExtensionList(
   const UnicodeString & Path, const UnicodeString & PathId, TStringList * DeletedExtensions)
   const UnicodeString & Path, const UnicodeString & PathId, TStringList * DeletedExtensions)
 {
 {
-  TSearchRecChecked SearchRec;
+  TSearchRecOwned SearchRec;
   int FindAttrs = faReadOnly | faArchive;
   int FindAttrs = faReadOnly | faArchive;
   if (FindFirstUnchecked(IncludeTrailingBackslash(Path) + L"*.*", FindAttrs, SearchRec) == 0)
   if (FindFirstUnchecked(IncludeTrailingBackslash(Path) + L"*.*", FindAttrs, SearchRec) == 0)
   {
   {
-    try
+    do
     {
     {
-      do
+      UnicodeString Id = TCustomCommandType::GetExtensionId(SearchRec.Name);
+      if (!Id.IsEmpty())
       {
       {
-        UnicodeString Id = TCustomCommandType::GetExtensionId(SearchRec.Name);
-        if (!Id.IsEmpty())
+        Id = IncludeTrailingBackslash(PathId) + Id;
+        if (DeletedExtensions->IndexOf(Id) >= 0)
+        {
+          // reconstruct the list, so that we remove the commands that no longer exists
+          AddToList(FExtensionsDeleted, Id, L"|");
+        }
+        else
         {
         {
-          Id = IncludeTrailingBackslash(PathId) + Id;
-          if (DeletedExtensions->IndexOf(Id) >= 0)
+          std::unique_ptr<TCustomCommandType> CustomCommand(new TCustomCommandType());
+          CustomCommand->Id = Id;
+
+          try
           {
           {
-            // reconstruct the list, so that we remove the commands that no longer exists
-            AddToList(FExtensionsDeleted, Id, L"|");
+            CustomCommand->LoadExtension(IncludeTrailingBackslash(Path) + SearchRec.Name);
+            FExtensionList->Add(CustomCommand.release());
           }
           }
-          else
+          catch (...)
           {
           {
-            std::unique_ptr<TCustomCommandType> CustomCommand(new TCustomCommandType());
-            CustomCommand->Id = Id;
-
-            try
-            {
-              CustomCommand->LoadExtension(IncludeTrailingBackslash(Path) + SearchRec.Name);
-              FExtensionList->Add(CustomCommand.release());
-            }
-            catch (...)
-            {
-              // skip invalid extension files
-            }
+            // skip invalid extension files
           }
           }
         }
         }
       }
       }
-      while (FindNextChecked(SearchRec) == 0);
-    }
-    __finally
-    {
-      FindClose(SearchRec);
     }
     }
+    while (FindNextChecked(SearchRec) == 0);
   }
   }
 }
 }
 //---------------------------------------------------------------------------
 //---------------------------------------------------------------------------
@@ -2365,7 +2358,7 @@ TStrings * __fastcall TWinConfiguration::FindTemporaryFolders()
   TStrings * Result = new TStringList();
   TStrings * Result = new TStringList();
   try
   try
   {
   {
-    TSearchRecChecked SRec;
+    TSearchRecOwned SRec;
     UnicodeString Mask = TemporaryDir(true);
     UnicodeString Mask = TemporaryDir(true);
     UnicodeString Directory = ExtractFilePath(Mask);
     UnicodeString Directory = ExtractFilePath(Mask);
     if (FindFirstUnchecked(Mask, faDirectory, SRec) == 0)
     if (FindFirstUnchecked(Mask, faDirectory, SRec) == 0)