Pārlūkot izejas kodu

When opening a session in an existing instance of WinSCP, any idle instance can be used, not only the latest one.

Source commit: e0bfeaea0c47cb81139ffa86f4bf96cb9bc7d480
Martin Prikryl 9 gadi atpakaļ
vecāks
revīzija
f6ab9e6946

+ 8 - 33
source/forms/CustomScpExplorer.cpp

@@ -367,31 +367,6 @@ __fastcall TCustomScpExplorerForm::~TCustomScpExplorerForm()
 
 }
 //---------------------------------------------------------------------------
-LRESULT WINAPI TCustomScpExplorerForm::HiddenWindowProc(
-  HWND HWnd, UINT Message, WPARAM WParam, LPARAM LParam)
-{
-  LRESULT Result;
-  if (Message == WM_COPYDATA)
-  {
-    LONG_PTR Ptr = GetWindowLongPtr(HWnd, GWLP_USERDATA);
-    TCustomScpExplorerForm * Form = reinterpret_cast<TCustomScpExplorerForm *>(Ptr);
-
-    TMessage AMessage;
-    AMessage.Msg = Message;
-    AMessage.WParam = WParam;
-    AMessage.LParam = LParam;
-    AMessage.Result = 0;
-    Form->WMCopyData(AMessage);
-
-    Result = AMessage.Result;
-  }
-  else
-  {
-    Result = DefWindowProc(HWnd, Message, WParam, LParam);
-  }
-  return Result;
-}
-//---------------------------------------------------------------------------
 void __fastcall TCustomScpExplorerForm::WMCopyData(TMessage & Message)
 {
   PCOPYDATASTRUCT CopyData = reinterpret_cast<PCOPYDATASTRUCT>(Message.LParam);
@@ -419,9 +394,13 @@ void __fastcall TCustomScpExplorerForm::WMCopyData(TMessage & Message)
           }
           break;
 
-      default:
-        Result = false;
-        break;
+        case TCopyDataMessage::MainWindowCheck:
+          Result = true;
+          break;
+
+        default:
+          Result = false;
+          break;
       }
     }
   }
@@ -432,7 +411,7 @@ void __fastcall TCustomScpExplorerForm::WMCopyData(TMessage & Message)
 void __fastcall TCustomScpExplorerForm::CreateHiddenWindow()
 {
   WNDCLASS WindowClass = {0};
-  WindowClass.lpfnWndProc = HiddenWindowProc;
+  WindowClass.lpfnWndProc = DefWindowProc;
   WindowClass.hInstance = HInstance;
   WindowClass.lpszClassName = HIDDEN_WINDOW_NAME;
 
@@ -442,10 +421,6 @@ void __fastcall TCustomScpExplorerForm::CreateHiddenWindow()
   {
     FHiddenWindow = CreateWindow(HIDDEN_WINDOW_NAME, L"",
       WS_POPUP, 0, 0, 0, 0, 0, 0, HInstance, NULL);
-    if (FHiddenWindow != NULL)
-    {
-      SetWindowLongPtr(FHiddenWindow, GWLP_USERDATA, reinterpret_cast<LONG_PTR>(this));
-    }
   }
 }
 //---------------------------------------------------------------------------

+ 0 - 1
source/forms/CustomScpExplorer.h

@@ -289,7 +289,6 @@ private:
   void __fastcall EnableDDTransferConfirmation(TObject * Sender);
   void __fastcall CollectItemsWithTextDisplayMode(TWinControl * Control);
   void __fastcall CreateHiddenWindow();
-  static LRESULT WINAPI HiddenWindowProc(HWND HWnd, UINT Message, WPARAM WParam, LPARAM LParam);
   bool __fastcall IsQueueAutoPopup();
   void __fastcall UpdateSessionsPageControlHeight();
   TDragDropFilesEx * __fastcall CreateDragDropFilesEx();

+ 8 - 2
source/windows/WinInterface.h

@@ -485,11 +485,11 @@ void __fastcall ReleaseAnimationsModule();
 void __fastcall ForceTracing();
 #endif
 //---------------------------------------------------------------------------
-#define HIDDEN_WINDOW_NAME L"WinSCPHiddenWindow2"
+#define HIDDEN_WINDOW_NAME L"WinSCPHiddenWindow3"
 //---------------------------------------------------------------------------
 struct TCopyDataMessage
 {
-  enum { CommandCanCommandLine, CommandCommandLine };
+  enum { CommandCanCommandLine, CommandCommandLine, MainWindowCheck };
   static const unsigned int Version1 = 1;
 
   unsigned int Version;
@@ -499,6 +499,12 @@ struct TCopyDataMessage
   {
     wchar_t CommandLine[10240];
   };
+
+  TCopyDataMessage()
+  {
+    Version = TCopyDataMessage::Version1;
+    Command = static_cast<unsigned int>(-1);
+  }
 };
 //---------------------------------------------------------------------------
 class TWinInteractiveCustomCommand : public TInteractiveCustomCommand

+ 87 - 60
source/windows/WinMain.cpp

@@ -447,95 +447,122 @@ void __fastcall MaintenanceTask()
   CoreMaintenanceTask();
 }
 //---------------------------------------------------------------------------
-struct TFindProcessMainWindowParam
+typedef std::vector<HWND> THandles;
+typedef std::map<unsigned long, THandles> TProcesses;
+//---------------------------------------------------------------------------
+BOOL __stdcall EnumOtherInstances(HWND Handle, LPARAM AParam)
 {
+  TProcesses & Processes = *reinterpret_cast<TProcesses *>(AParam);
+
   unsigned long ProcessId;
-  HWND HiddenWindow;
-  HWND MainWindow;
-};
+  if (GetWindowThreadProcessId(Handle, &ProcessId) != 0)
+  {
+    Processes[ProcessId].push_back(Handle);
+  }
+
+  return TRUE;
+}
+//---------------------------------------------------------------------------
+static bool __fastcall SendCopyDataMessage(HWND Window, TCopyDataMessage & Message)
+{
+  COPYDATASTRUCT CopyData;
+  CopyData.cbData = sizeof(Message);
+  CopyData.lpData = &Message;
+
+  LRESULT SendResult =
+    SendMessage(Window, WM_COPYDATA,
+       reinterpret_cast<WPARAM>(HInstance), reinterpret_cast<LPARAM>(&CopyData));
+  bool Result = (SendResult > 0);
+  return Result;
+}
 //---------------------------------------------------------------------------
-BOOL __stdcall FindProcessMainWindow(HWND Handle, LPARAM AParam)
+static void __fastcall FindOtherInstances(THandles & OtherInstances)
 {
-  TFindProcessMainWindowParam & Param = *reinterpret_cast<TFindProcessMainWindowParam *>(AParam);
+  TProcesses Processes;
 
-  unsigned long ProcessId;
-  if ((Handle != Param.HiddenWindow) &&
-      (Param.MainWindow == 0) && // optimization
-      (GetWindowThreadProcessId(Handle, &ProcessId) != 0) &&
-      (ProcessId == Param.ProcessId))
+  // FindWindow is optimization (if there's no hidden window, no point enumerating all windows to find some)
+  if ((FindWindow(HIDDEN_WINDOW_NAME, NULL) != NULL) &&
+      EnumWindows(EnumOtherInstances, reinterpret_cast<LPARAM>(&Processes)))
   {
     TCopyDataMessage Message;
-    Message.Version = TCopyDataMessage::Version1;
 
-    COPYDATASTRUCT CopyData;
-    CopyData.cbData = sizeof(Message);
-    CopyData.lpData = &Message;
+    Message.Command = TCopyDataMessage::MainWindowCheck;
 
-    Message.Command = TCopyDataMessage::CommandCanCommandLine;
+    TProcesses::const_iterator ProcessI = Processes.begin();
+    while (ProcessI != Processes.end())
+    {
+      HWND HiddenWindow = NULL;
+      THandles::const_iterator WindowI = ProcessI->second.begin();
 
-    LRESULT SendResult =
-      SendMessage(Handle, WM_COPYDATA, reinterpret_cast<WPARAM>(HInstance),
-        reinterpret_cast<LPARAM>(&CopyData));
+      while ((HiddenWindow == NULL) && (WindowI != ProcessI->second.end()))
+      {
+        wchar_t ClassName[1024];
+        if (GetClassName(*WindowI, ClassName, LENOF(ClassName)) != 0)
+        {
+          NULL_TERMINATE(ClassName);
 
-    if (SendResult > 0)
-    {
-      Param.MainWindow = Handle;
+          if (wcscmp(ClassName, HIDDEN_WINDOW_NAME) == 0)
+          {
+            HiddenWindow = *WindowI;
+          }
+        }
+        WindowI++;
+      }
+
+      if (HiddenWindow != NULL)
+      {
+        WindowI = ProcessI->second.begin();
+
+        while (WindowI != ProcessI->second.end())
+        {
+          if (*WindowI != HiddenWindow) // optimization
+          {
+            if (SendCopyDataMessage(*WindowI, Message))
+            {
+              OtherInstances.push_back(*WindowI);
+              break;
+            }
+          }
+          WindowI++;
+        }
+      }
+
+      ProcessI++;
     }
   }
-
-  return TRUE;
 }
 //---------------------------------------------------------------------------
 bool __fastcall SendToAnotherInstance()
 {
-  HWND HiddenWindow = FindWindow(HIDDEN_WINDOW_NAME, NULL);
-  bool Result = (HiddenWindow != NULL);
-  if (Result)
-  {
-    TCopyDataMessage Message;
-    Message.Version = TCopyDataMessage::Version1;
+  THandles OtherInstances;
+  FindOtherInstances(OtherInstances);
 
-    COPYDATASTRUCT CopyData;
-    CopyData.cbData = sizeof(Message);
-    CopyData.lpData = &Message;
+  bool Result = false;
+  THandles::const_iterator I = OtherInstances.begin();
+  while (!Result && (I != OtherInstances.end()))
+  {
+    HWND Handle = *I;
 
-    // this test is actually redundant, it just a kind of optimization to avoid expensive
-    // EnumWindows, we can achieve the same by testing FindProcessMainWindowParam.MainWindow,
-    // before sending CommandCommandLine
+    TCopyDataMessage Message;
     Message.Command = TCopyDataMessage::CommandCanCommandLine;
-    LRESULT SendResult =
-      SendMessage(HiddenWindow, WM_COPYDATA, reinterpret_cast<WPARAM>(HInstance),
-        reinterpret_cast<LPARAM>(&CopyData));
-    Result = (SendResult > 0);
 
-    if (Result)
+    if (SendCopyDataMessage(Handle, Message))
     {
-      TFindProcessMainWindowParam FindProcessMainWindowParam;
-      if (GetWindowThreadProcessId(HiddenWindow, &FindProcessMainWindowParam.ProcessId) != 0)
-      {
-        FindProcessMainWindowParam.HiddenWindow = HiddenWindow;
-        FindProcessMainWindowParam.MainWindow = 0;
-        if (EnumWindows(FindProcessMainWindow, reinterpret_cast<LPARAM>(&FindProcessMainWindowParam)) &&
-            (FindProcessMainWindowParam.MainWindow != 0))
-        {
-          // Restore window, if minimized
-          ShowWindow(FindProcessMainWindowParam.MainWindow, SW_RESTORE);
-          // bring it to foreground
-          SetForegroundWindow(FindProcessMainWindowParam.MainWindow);
-        }
-      }
+      // Restore window, if minimized
+      ShowWindow(Handle, SW_RESTORE);
+      // bring it to foreground
+      SetForegroundWindow(Handle);
 
       Message.Command = TCopyDataMessage::CommandCommandLine;
       wcsncpy(Message.CommandLine, CmdLine, LENOF(Message.CommandLine));
       NULL_TERMINATE(Message.CommandLine);
 
-
-      LRESULT SendResult =
-        SendMessage(HiddenWindow, WM_COPYDATA,
-          reinterpret_cast<WPARAM>(HInstance), reinterpret_cast<LPARAM>(&CopyData));
-      Result = (SendResult > 0);
+      Result = SendCopyDataMessage(Handle, Message);
     }
+
+    I++;
   }
+
   return Result;
 }
 //---------------------------------------------------------------------------