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

In UWP, files can be downloaded directly to an external drop location even without a loaded drag&drop shell extension.

Part of "Make WinSCP available in Windows Store (UWP/AppX package)"
https://winscp.net/tracker/1639
(UWP-only subset of dev branch commit dc85563)

Counters DownloadsDragDropQueue + DownloadsDragDropFakeFile

(cherry picked from commit dc855630a2)

# Conflicts:
#	source/resource/TextsWin.h
#	source/resource/TextsWin1.rc
#	translations/translate.web.ini

Source commit: 5c7069bac3e08f2f19c227d38eaffe989e73f4f8
This commit is contained in:
Martin Prikryl
2018-05-02 14:01:43 +00:00
parent 83c77d5cac
commit be8d3acbc1
11 changed files with 132 additions and 22 deletions

View File

@@ -96,7 +96,10 @@
<BuildOrder>3</BuildOrder>
</DelphiCompile>
<DelphiCompile Include="packages\my\CompThread.pas">
<BuildOrder>4</BuildOrder>
<BuildOrder>22</BuildOrder>
</DelphiCompile>
<DelphiCompile Include="packages\my\DirectoryMonitor.pas">
<BuildOrder>23</BuildOrder>
</DelphiCompile>
<ResFiles Include="packages\my\DiscMon.dcr">
<BuildOrder>6</BuildOrder>

View File

@@ -208,7 +208,7 @@ DllMain(HINSTANCE HInstance, DWORD Reason, LPVOID /*Reserved*/)
if (GRefThisDll == 0)
{
GLogMutex = CreateMutex(NULL, false, L"WinSCPDragExtLogMutex");
GLogMutex = CreateMutex(NULL, false, DRAG_EXT_RUNNING_MUTEX);
for (int Root = 0; Root <= 1; Root++)
{

View File

@@ -4,6 +4,7 @@
//---------------------------------------------------------------------------
#define DRAG_EXT_MAPPING L"WinSCPDragExtMapping"
#define DRAG_EXT_MUTEX L"WinSCPDragExtMutex"
#define DRAG_EXT_RUNNING_MUTEX L"WinSCPDragExtLogMutex"
#define DRAG_EXT_DUMMY_DIR_PREFIX L"scp"
#define DRAG_EXT_DUMMY_DIR_PREFIX_LEN 3
//---------------------------------------------------------------------------

View File

@@ -35,6 +35,7 @@
#include <Consts.hpp>
#include <DateUtils.hpp>
#include <TB2Common.hpp>
#include <DirectoryMonitor.hpp>
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma link "CustomDirView"
@@ -6583,7 +6584,7 @@ void __fastcall TCustomScpExplorerForm::RemoteFileControlDDCreateDragFileList(
if (WinConfiguration->DDExtEnabled)
{
if (!WinConfiguration->DDExtInstalled)
if (!IsUWP() && !WinConfiguration->DDExtInstalled)
{
Configuration->Usage->Inc(L"DownloadsDragDropExternalExtNotInstalled");
throw ExtException(NULL, LoadStr(DRAGEXT_TARGET_NOT_INSTALLED2), HELP_DRAGEXT_TARGET_NOT_INSTALLED);
@@ -6592,19 +6593,61 @@ void __fastcall TCustomScpExplorerForm::RemoteFileControlDDCreateDragFileList(
}
}
//---------------------------------------------------------------------------
void __fastcall TCustomScpExplorerForm::DDFakeCreated(TObject * /*Sender*/, const UnicodeString FileName)
{
if (DebugAlwaysTrue(!FDragExtFakeDirectory.IsEmpty()) &&
SameText(ExtractFileName(FileName), ExtractFileName(FDragExtFakeDirectory)))
{
FFakeFileDropTarget = FileName;
}
}
//---------------------------------------------------------------------------
void __fastcall TCustomScpExplorerForm::DDExtInitDrag(TFileList * FileList,
bool & Created)
{
FFakeFileDropTarget = UnicodeString();
FDragExtFakeDirectory =
ExcludeTrailingBackslash(WinConfiguration->TemporaryDir());
if (!ForceDirectories(ApiPath(FDragExtFakeDirectory)))
{
throw Exception(FMTLOAD(CREATE_TEMP_DIR_ERROR, (FDragExtFakeDirectory)));
}
if (IsUWP())
{
FileSetAttr(ApiPath(FDragExtFakeDirectory), faHidden);
}
FileList->AddItem(NULL, FDragExtFakeDirectory);
Created = true;
if (IsUWP() && !WinConfiguration->IsDDExtRunning())
{
FDragFakeMonitors = new TObjectList();
for (char Drive = FirstDrive; Drive <= LastDrive; Drive++)
{
std::unique_ptr<TDirectoryMonitor> Monitor(new TDirectoryMonitor(this));
DriveInfo->ReadDriveStatus(Drive, dsSize | dsImageIndex);
TDriveInfoRec * DriveInfoRec = DriveInfo->Data[Drive];
if (DriveInfoRec->Valid &&
(DriveInfoRec->DriveType != DRIVE_CDROM))
{
try
{
Monitor->Path = UnicodeString(Drive) + L":\\";
Monitor->WatchSubtree = true;
Monitor->WatchFilters = FILE_NOTIFY_CHANGE_DIR_NAME;
Monitor->OnCreated = DDFakeCreated;
Monitor->Active = true;
FDragFakeMonitors->Add(Monitor.release());
}
catch (Exception & E)
{
// Ignore errors watching not-ready drives
}
}
}
}
FDDExtMapFile = CreateFileMappingA((HANDLE)0xFFFFFFFF, NULL, PAGE_READWRITE,
0, sizeof(TDragExtCommStruct), AnsiString(DRAG_EXT_MAPPING).c_str());
@@ -6669,6 +6712,11 @@ void __fastcall TCustomScpExplorerForm::RemoteFileControlDDEnd(TObject * Sender)
// Drops of local files (uploads) are handled in QueueDDProcessDropped.
SAFE_DESTROY(FDDFileList);
if (IsUWP() && !FFakeFileDropTarget.IsEmpty())
{
RemoveDir(ApiPath(FFakeFileDropTarget));
}
if ((FDDExtMapFile != NULL) || (FDDTargetControl == QueueView3))
{
try
@@ -6712,9 +6760,9 @@ void __fastcall TCustomScpExplorerForm::RemoteFileControlDDEnd(TObject * Sender)
}
TTransferOperationParam Param;
bool Internal;
UnicodeString CounterName;
bool ForceQueue;
if (!DDGetTarget(Param.TargetDirectory, ForceQueue, Internal))
if (!DDGetTarget(Param.TargetDirectory, ForceQueue, CounterName))
{
// we get drInvalid both if d&d was intercepted by ddext,
// and when users drops on no-drop location.
@@ -6731,7 +6779,7 @@ void __fastcall TCustomScpExplorerForm::RemoteFileControlDDEnd(TObject * Sender)
}
else
{
// download using ddext
// download using fake file
Param.Temp = false;
Param.DragDrop = true;
if (ForceQueue)
@@ -6746,8 +6794,7 @@ void __fastcall TCustomScpExplorerForm::RemoteFileControlDDEnd(TObject * Sender)
if (RemoteFileControlFileOperation(Sender, Operation,
(WinConfiguration->DDTransferConfirmation == asOff), &Param))
{
Configuration->Usage->Inc(
Internal ? L"DownloadsDragDropInternal" : L"DownloadsDragDropExternalExt");
Configuration->Usage->Inc(CounterName);
}
}
}
@@ -6756,8 +6803,14 @@ void __fastcall TCustomScpExplorerForm::RemoteFileControlDDEnd(TObject * Sender)
{
CloseHandle(FDDExtMapFile);
FDDExtMapFile = NULL;
if (IsUWP())
{
delete FDragFakeMonitors;
FDragFakeMonitors = NULL;
}
RemoveDir(ApiPath(FDragExtFakeDirectory));
FDragExtFakeDirectory = L"";
FFakeFileDropTarget = UnicodeString();
}
}
@@ -6789,16 +6842,23 @@ void __fastcall TCustomScpExplorerForm::RemoteFileControlDDGiveFeedback(
}
//---------------------------------------------------------------------------
bool __fastcall TCustomScpExplorerForm::DDGetTarget(
UnicodeString & Directory, bool & ForceQueue, bool & Internal)
UnicodeString & Directory, bool & ForceQueue, UnicodeString & CounterName)
{
bool Result;
if (FDDTargetControl == QueueView3)
{
Directory = DefaultDownloadTargetDirectory();
Result = true;
Internal = true;
CounterName = L"DownloadsDragDropQueue";
ForceQueue = true;
}
else if (IsUWP() && !FFakeFileDropTarget.IsEmpty())
{
Directory = ExcludeTrailingBackslash(ExtractFilePath(FFakeFileDropTarget));
Result = true;
ForceQueue = false;
CounterName = L"DownloadsDragDropFakeFile";
}
else
{
ForceQueue = false;
@@ -6820,7 +6880,7 @@ bool __fastcall TCustomScpExplorerForm::DDGetTarget(
if (Result)
{
Directory = ExtractFilePath(CommStruct->DropDest);
Internal = false;
CounterName = L"DownloadsDragDropExternalExt";
}
UnmapViewOfFile(CommStruct);
}

View File

@@ -202,6 +202,7 @@ private:
TStringList * FErrorList;
HANDLE FDDExtMutex;
UnicodeString FDragExtFakeDirectory;
TObjectList * FDragFakeMonitors;
TStrings * FDelayedDeletionList;
TTimer * FDelayedDeletionTimer;
TStrings * FDDFileList;
@@ -327,6 +328,7 @@ protected:
TPoint FLastContextPopupScreenPoint;
bool FRemoteDirViewWasFocused;
bool FDoNotIdleCurrentTerminal;
UnicodeString FFakeFileDropTarget;
virtual bool __fastcall CopyParamDialog(TTransferDirection Direction,
TTransferType Type, bool Temp, TStrings * FileList,
@@ -419,8 +421,9 @@ protected:
bool __fastcall ExecuteFileOperation(TFileOperation Operation, TOperationSide Side,
TStrings * FileList, bool NoConfirmation, void * Param);
virtual bool __fastcall DDGetTarget(UnicodeString & Directory,
bool & ForceQueue, bool & Internal);
bool & ForceQueue, UnicodeString & CounterName);
virtual void __fastcall DDExtInitDrag(TFileList * FileList, bool & Created);
void __fastcall DDFakeCreated(TObject * Sender, const UnicodeString FileName);
virtual void __fastcall SideEnter(TOperationSide Side);
virtual TOperationSide __fastcall GetSide(TOperationSide Side);
TStrings * __fastcall PanelExport(TOperationSide Side, TPanelExport Export);

View File

@@ -1214,8 +1214,8 @@ void __fastcall TPreferencesDialog::UpdateControls()
}
SetLabelHintPopup(CopyParamLabel, InfoStr);
EnableControl(DDExtEnabledButton, WinConfiguration->DDExtInstalled);
EnableControl(DDExtEnabledLabel, WinConfiguration->DDExtInstalled);
EnableControl(DDExtEnabledButton, IsUWP() || WinConfiguration->DDExtInstalled);
EnableControl(DDExtEnabledLabel, DDExtEnabledButton->Enabled);
EnableControl(DDExtDisabledPanel, DDExtDisabledButton->Checked);
EnableControl(DDTemporaryDirectoryEdit, DDCustomTemporaryDirectoryButton->Enabled &&
DDCustomTemporaryDirectoryButton->Checked);

View File

@@ -1343,7 +1343,7 @@ object PreferencesDialog: TPreferencesDialog
Width = 364
Height = 17
Anchors = [akLeft, akTop, akRight]
Caption = 'Use &shell extension'
Caption = 'Determine drop target by dragging a &fake file'
TabOrder = 1
OnClick = ControlChange
end
@@ -1353,7 +1353,7 @@ object PreferencesDialog: TPreferencesDialog
Width = 356
Height = 17
Anchors = [akLeft, akTop, akRight]
Caption = 'Use &temporary folder'
Caption = 'Download files via &temporary folder'
TabOrder = 2
OnClick = ControlChange
end

View File

@@ -1449,7 +1449,7 @@ void __fastcall TScpCommanderForm::LocalFileControlDDDragOver(TObject * /*Sender
}
//---------------------------------------------------------------------------
bool __fastcall TScpCommanderForm::DDGetTarget(
UnicodeString & Directory, bool & ForceQueue, bool & Internal)
UnicodeString & Directory, bool & ForceQueue, UnicodeString & CounterName)
{
bool Result;
if (!FDDExtTarget.IsEmpty())
@@ -1457,12 +1457,12 @@ bool __fastcall TScpCommanderForm::DDGetTarget(
Directory = FDDExtTarget;
FDDExtTarget = L"";
Result = true;
Internal = true;
CounterName = L"DownloadsDragDropInternal";
ForceQueue = false;
}
else
{
Result = TCustomScpExplorerForm::DDGetTarget(Directory, ForceQueue, Internal);
Result = TCustomScpExplorerForm::DDGetTarget(Directory, ForceQueue, CounterName);
}
return Result;
}

View File

@@ -536,7 +536,7 @@ protected:
TOperationSide Side);
bool __fastcall InternalDDDownload(UnicodeString & TargetDirectory);
virtual bool __fastcall DDGetTarget(
UnicodeString & Directory, bool & ForceQueue, bool & Internal);
UnicodeString & Directory, bool & ForceQueue, UnicodeString & CounterName);
virtual void __fastcall DDExtInitDrag(TFileList * FileList, bool & Created);
virtual void __fastcall SideEnter(TOperationSide Side);
void __fastcall SaveCommandLine();

View File

@@ -493,6 +493,7 @@ void __fastcall TWinConfiguration::Default()
FDDWarnLackOfTempSpace = true;
FDDWarnLackOfTempSpaceRatio = 1.1;
FDDExtEnabled = DDExtInstalled;
FDDFakeFile = true;
FDDExtTimeout = MSecsPerSec;
FDeleteToRecycleBin = true;
FSelectDirectories = false;
@@ -915,6 +916,7 @@ THierarchicalStorage * TWinConfiguration::CreateScpStorage(bool & SessionList)
KEY(Bool, UseSharedBookmarks); \
KEY(Integer, LocaleSafe); \
KEY(Bool, DDExtEnabled); \
KEY(Bool, DDFakeFile); \
KEY(Integer, DDExtTimeout); \
KEY(Bool, DefaultDirIsHome); \
KEY(Bool, TemporaryDirectoryAppendSession); \
@@ -1605,6 +1607,23 @@ bool __fastcall TWinConfiguration::GetDDExtInstalled()
return (FDDExtInstalled > 0);
}
//---------------------------------------------------------------------------
bool __fastcall TWinConfiguration::IsDDExtRunning()
{
bool Result;
if (!DDExtInstalled)
{
Result = false;
}
else
{
HANDLE H = OpenMutex(SYNCHRONIZE, False, DRAG_EXT_RUNNING_MUTEX);
Result = (H != NULL);
CloseHandle(H);
}
return Result;
}
//---------------------------------------------------------------------------
RawByteString __fastcall TWinConfiguration::StronglyRecryptPassword(RawByteString Password, UnicodeString Key)
{
RawByteString Dummy;
@@ -1799,9 +1818,28 @@ void __fastcall TWinConfiguration::SetDDTemporaryDirectory(UnicodeString value)
SET_CONFIG_PROPERTY(DDTemporaryDirectory);
}
//---------------------------------------------------------------------------
bool __fastcall TWinConfiguration::GetDDExtEnabled()
{
if (IsUWP())
{
return FDDFakeFile;
}
else
{
return FDDExtEnabled;
}
}
//---------------------------------------------------------------------------
void __fastcall TWinConfiguration::SetDDExtEnabled(bool value)
{
SET_CONFIG_PROPERTY(DDExtEnabled);
if (IsUWP())
{
SET_CONFIG_PROPERTY(DDFakeFile);
}
else
{
SET_CONFIG_PROPERTY(DDExtEnabled);
}
}
//---------------------------------------------------------------------------
void __fastcall TWinConfiguration::SetDDExtTimeout(int value)

View File

@@ -355,6 +355,7 @@ private:
UnicodeString FDDTemporaryDirectory;
bool FDDWarnLackOfTempSpace;
bool FDDExtEnabled;
bool FDDFakeFile;
int FDDExtInstalled;
int FDDExtTimeout;
bool FConfirmClosingSession;
@@ -464,6 +465,7 @@ private:
void __fastcall SetDDTemporaryDirectory(UnicodeString value);
void __fastcall SetDDWarnLackOfTempSpace(bool value);
void __fastcall SetDDExtEnabled(bool value);
bool __fastcall GetDDExtEnabled();
void __fastcall SetDDExtTimeout(int value);
void __fastcall SetConfirmClosingSession(bool value);
void __fastcall SetDDWarnLackOfTempSpaceRatio(double value);
@@ -577,6 +579,8 @@ protected:
void __fastcall ReleaseExtensionTranslations();
void __fastcall LoadExtensionTranslations();
__property bool DDFakeFile = { read=FDDFakeFile, write=FDDFakeFile };
public:
__fastcall TWinConfiguration();
virtual __fastcall ~TWinConfiguration();
@@ -612,6 +616,7 @@ public:
UnicodeString __fastcall ExtensionStringTranslation(const UnicodeString & ExtensionId, const UnicodeString & S);
UnicodeString __fastcall UniqueExtensionName(const UnicodeString & ExtensionName, int Counter);
UnicodeString __fastcall GetProvisionaryExtensionId(const UnicodeString & FileName);
bool __fastcall IsDDExtRunning();
static void __fastcall RestoreFont(const TFontConfiguration & Configuration, TFont * Font);
static void __fastcall StoreFont(TFont * Font, TFontConfiguration & Configuration);
@@ -646,7 +651,7 @@ public:
__property bool UseSharedBookmarks = { read = FUseSharedBookmarks, write = SetUseSharedBookmarks};
__property UnicodeString DDTemporaryDirectory = { read=FDDTemporaryDirectory, write=SetDDTemporaryDirectory };
__property bool DDWarnLackOfTempSpace = { read=FDDWarnLackOfTempSpace, write=SetDDWarnLackOfTempSpace };
__property bool DDExtEnabled = { read=FDDExtEnabled, write=SetDDExtEnabled };
__property bool DDExtEnabled = { read=GetDDExtEnabled, write=SetDDExtEnabled };
__property bool DDExtInstalled = { read=GetDDExtInstalled };
__property int DDExtTimeout = { read=FDDExtTimeout, write=SetDDExtTimeout };
__property bool ConfirmClosingSession = { read=FConfirmClosingSession, write=SetConfirmClosingSession };