فهرست منبع

Bug 1666: Optionally disable running shell operations on separate thread

https://winscp.net/tracker/1666
(cherry picked from commit 9523f4177606a8ffa8c889bdd1830145c06cf5ff)

# Conflicts:
#	source/packages/my/OperationWithTimeout.pas
#	source/windows/WinConfiguration.cpp

Source commit: 861f86522446eaf254a434fdb107da98fed4111b
Martin Prikryl 7 سال پیش
والد
کامیت
04d93edbf8
3فایلهای تغییر یافته به همراه41 افزوده شده و 16 حذف شده
  1. 26 16
      source/packages/my/OperationWithTimeout.pas
  2. 12 0
      source/windows/WinConfiguration.cpp
  3. 3 0
      source/windows/WinConfiguration.h

+ 26 - 16
source/packages/my/OperationWithTimeout.pas

@@ -16,6 +16,9 @@ function ShellFolderParseDisplayNameWithTimeout(
   ShellFolder: IShellFolder; hwndOwner: HWND; pbcReserved: Pointer; lpszDisplayName: POLESTR;
   out pchEaten: ULONG; out ppidl: PItemIDList; var dwAttributes: ULONG; Timeout: Integer): HResult;
 
+var
+  TimeoutShellOperations: Boolean = True;
+
 implementation
 
 uses
@@ -93,26 +96,33 @@ var
 begin
 // When running from IDE, it triggers starting/exiting the thread taking ages.
 // So in IDE we revert to single-thread approach.
-{$IFDEF IDE}
-  OperationEvent(Operation);
-  Result := True;
-{$ELSE}
-  // Have to start new thread for each request. When shared thread is used, it eventually hangs.
-  // Most probably do to the fact that we violate COM threading model.
-  // So using a new thread for each request, is only a hack that happens to work by pure luck.
-  // We may want to use shared thread at least for COM-free operations, like SHGetFileInfo.
-  Thread := TOperationWithTimeoutThread.Create(Operation, OperationEvent);
-  Thread.Resume;
-  Result := Thread.WaitFor(MSecsPerSec);
-  if Result then
+{$IFNDEF IDE}
+  if not TimeoutShellOperations then
+{$ENDIF}
   begin
-    Thread.Free;
+    OperationEvent(Operation);
+    Result := True;
   end
+{$IFNDEF IDE}
     else
   begin
-    // There's a chance for memory leak, if thread is terminated
-    // between WaitFor() and this line
-    Thread.FreeOnTerminate := True;
+    // Have to start new thread for each request. When shared thread is used, it eventually hangs.
+    // Most probably do to the fact that we violate COM threading model.
+    // So using a new thread for each request, is only a hack that happens to work by pure luck.
+    // We may want to use shared thread at least for COM-free operations, like SHGetFileInfo.
+    Thread := TOperationWithTimeoutThread.Create(Operation, OperationEvent);
+    Thread.Resume;
+    Result := Thread.WaitFor(MSecsPerSec);
+    if Result then
+    begin
+      Thread.Free;
+    end
+      else
+    begin
+      // There's a chance for memory leak, if thread is terminated
+      // between WaitFor() and this line
+      Thread.FreeOnTerminate := True;
+    end;
   end;
 {$ENDIF}
 end;

+ 12 - 0
source/windows/WinConfiguration.cpp

@@ -20,6 +20,7 @@
 #include <Math.hpp>
 #include <StrUtils.hpp>
 #include <Generics.Defaults.hpp>
+#include <OperationWithTimeout.hpp>
 #include "FileInfo.h"
 //---------------------------------------------------------------------------
 #pragma package(smart_init)
@@ -969,6 +970,7 @@ THierarchicalStorage * TWinConfiguration::CreateScpStorage(bool & SessionList)
     KEY(Integer,  LastMachineInstallations); \
     KEYEX(String, FExtensionsDeleted, L"ExtensionsDeleted"); \
     KEYEX(String, FExtensionsOrder, L"ExtensionsOrder"); \
+    KEY(Bool,  TimeoutShellOperations); \
   ); \
   BLOCK(L"Interface\\Editor", CANCREATE, \
     KEYEX(String,   Editor.Font.FontName, L"FontName2"); \
@@ -2533,6 +2535,16 @@ void __fastcall TWinConfiguration::SetLockedInterface(bool value)
   SET_CONFIG_PROPERTY(LockedInterface);
 }
 //---------------------------------------------------------------------------
+bool __fastcall TWinConfiguration::GetTimeoutShellOperations()
+{
+  return ::TimeoutShellOperations;
+}
+//---------------------------------------------------------------------------
+void __fastcall TWinConfiguration::SetTimeoutShellOperations(bool value)
+{
+  ::TimeoutShellOperations = value;
+}
+//---------------------------------------------------------------------------
 TStringList * __fastcall TWinConfiguration::LoadJumpList(
   THierarchicalStorage * Storage, UnicodeString Name)
 {

+ 3 - 0
source/windows/WinConfiguration.h

@@ -535,6 +535,8 @@ private:
   TStrings * __fastcall GetCustomCommandOptions();
   void __fastcall SetCustomCommandOptions(TStrings * value);
   void __fastcall SetLockedInterface(bool value);
+  bool __fastcall GetTimeoutShellOperations();
+  void __fastcall SetTimeoutShellOperations(bool value);
   int __fastcall GetLocaleCompletenessTreshold();
 
   bool __fastcall GetDDExtInstalled();
@@ -714,6 +716,7 @@ public:
   __property TMasterPasswordPromptEvent OnMasterPasswordPrompt = { read = FOnMasterPasswordPrompt, write = FOnMasterPasswordPrompt };
   __property TStrings * CustomCommandOptions = { read = GetCustomCommandOptions, write = SetCustomCommandOptions };
   __property bool LockedInterface = { read = FLockedInterface, write = SetLockedInterface };
+  __property bool TimeoutShellOperations = { read = GetTimeoutShellOperations, write = SetTimeoutShellOperations };
   __property LCID DefaultLocale = { read = FDefaultLocale };
   __property int LocaleCompletenessTreshold = { read = GetLocaleCompletenessTreshold };
 };