1
0
mirror of https://github.com/winscp/winscp.git synced 2026-10-24 02:28:55 +03:00

Bug 2083: Workaround for an apparent bug in Windows 11 that prevents WinSCP from stopping Windows going to the sleep mode during transfers

https://winscp.net/tracker/2083

Source commit: 3db5f1e4d3a6e85e5c16559935f5273e1e905f6c
This commit is contained in:
Martin Prikryl
2022-06-03 14:30:27 +00:00
parent 0a01089bb7
commit 4b38960069
5 changed files with 94 additions and 1 deletions

View File

@@ -3022,6 +3022,11 @@ bool __fastcall IsWin10Build(unsigned int BuildNumber)
(OSVersionInfo.dwBuildNumber >= BuildNumber));
}
//---------------------------------------------------------------------------
bool IsWin11()
{
return IsWin10Build(22000);
}
//---------------------------------------------------------------------------
bool __fastcall IsWine()
{
HMODULE NtDll = GetModuleHandle(L"ntdll.dll");

View File

@@ -142,6 +142,7 @@ bool __fastcall IsWin7();
bool __fastcall IsWin8();
bool __fastcall IsWin10();
bool __fastcall IsWin10Build(unsigned int BuildNumber);
bool IsWin11();
bool __fastcall IsWine();
bool __fastcall IsUWP();
UnicodeString GetPackageName();

View File

@@ -5,6 +5,7 @@
#include "Common.h"
#include "FileOperationProgress.h"
#include "CoreMain.h"
#include "Interface.h"
//---------------------------------------------------------------------------
#define TRANSFER_BUF_SIZE 32768
//---------------------------------------------------------------------------
@@ -310,7 +311,7 @@ void __fastcall TFileOperationProgressType::Progress()
//---------------------------------------------------------------------------
void __fastcall TFileOperationProgressType::DoProgress()
{
SetThreadExecutionState(ES_SYSTEM_REQUIRED);
SystemRequired();
FOnProgress(*this);
}
//---------------------------------------------------------------------------

View File

@@ -49,6 +49,7 @@ void __fastcall BusyEnd(void * Token);
const unsigned int GUIUpdateInterval = 100;
void __fastcall SetNoGUI();
bool __fastcall ProcessGUI(bool Force = false);
void SystemRequired();
UnicodeString __fastcall AppNameString();
UnicodeString __fastcall SshVersionString();
void __fastcall CopyToClipboard(UnicodeString Text);

View File

@@ -2297,7 +2297,92 @@ bool CanShowTimeEstimate(TDateTime StartTime)
return (SecondsBetween(StartTime, Now()) >= 3);
}
//---------------------------------------------------------------------------
class TSystemRequiredThread : public TSignalThread
{
public:
TSystemRequiredThread();
void Required();
protected:
virtual bool __fastcall WaitForEvent();
virtual void __fastcall ProcessEvent();
private:
bool FRequired;
TDateTime FLastRequired;
};
//---------------------------------------------------------------------------
std::unique_ptr<TCriticalSection> SystemRequiredThreadSection(TraceInitPtr(new TCriticalSection()));
TSystemRequiredThread * SystemRequiredThread = NULL;
//---------------------------------------------------------------------------
TSystemRequiredThread::TSystemRequiredThread() :
TSignalThread(true), FRequired(false)
{
}
//---------------------------------------------------------------------------
void TSystemRequiredThread::Required()
{
// guarded in SystemRequired()
FLastRequired = Now();
TriggerEvent();
}
//---------------------------------------------------------------------------
bool __fastcall TSystemRequiredThread::WaitForEvent()
{
const int ExpireInterval = 5000;
bool Result = (TSignalThread::WaitForEvent(ExpireInterval) > 0);
if (!Result && !FTerminated)
{
TGuard Guard(SystemRequiredThreadSection.get());
if (!FTerminated && FRequired &&
(MilliSecondsBetween(Now(), FLastRequired) > ExpireInterval))
{
SetThreadExecutionState(ES_CONTINUOUS);
FLastRequired = TDateTime();
FRequired = false;
}
}
return Result;
}
//---------------------------------------------------------------------------
void __fastcall TSystemRequiredThread::ProcessEvent()
{
TGuard Guard(SystemRequiredThreadSection.get());
if (!FRequired &&
(FLastRequired != TDateTime()))
{
SetThreadExecutionState(ES_SYSTEM_REQUIRED | ES_CONTINUOUS);
FRequired = true;
}
}
//---------------------------------------------------------------------------
void SystemRequired()
{
if (IsWin11())
{
TGuard Guard(SystemRequiredThreadSection.get());
if (SystemRequiredThread == NULL)
{
SystemRequiredThread = new TSystemRequiredThread();
SystemRequiredThread->Start();
}
SystemRequiredThread->Required();
}
else
{
SetThreadExecutionState(ES_SYSTEM_REQUIRED);
}
}
//---------------------------------------------------------------------------
void GUIFinalize()
{
TPuttyCleanupThread::Finalize();
TSystemRequiredThread * Thread;
{
TGuard Guard(SystemRequiredThreadSection.get());
Thread = SystemRequiredThread;
SystemRequiredThread = NULL;
}
Thread->Terminate();
Thread->WaitFor();
delete Thread;
}