瀏覽代碼

When trying to open an inaccessible local directory, display an error message, instead of silently doing nothing

Source commit: 12da4e9bdee074951e9c4da15d445d15fe971221
Martin Prikryl 5 年之前
父節點
當前提交
1fbcd416d8

+ 27 - 7
source/packages/filemng/DirView.pas

@@ -404,6 +404,7 @@ function DropFiles(
   RenameOnCollision: Boolean; IsRecycleBin: Boolean; ConfirmDelete: Boolean; ConfirmOverwrite: Boolean; Paste: Boolean;
   Sender: TObject; OnDDFileOperation: TDDFileOperationEvent;
   out SourcePath: string; out SourceIsDirectory: Boolean): Boolean;
+procedure CheckCanOpenDirectory(Path: string);
 
 var
   LastClipBoardOperation: TClipBoardOperation;
@@ -619,6 +620,24 @@ begin
     else Result := False;
 end; {GetShellDisplayName}
 
+procedure CheckCanOpenDirectory(Path: string);
+var
+  DosError: Integer;
+  SRec: SysUtils.TSearchRec;
+begin
+  if not DirectoryExistsFix(Path) then
+    raise Exception.CreateFmt(SDirNotExists, [Path]);
+  DosError := SysUtils.FindFirst(ApiPath(IncludeTrailingPathDelimiter(Path) + '*.*'), FileAttr, SRec);
+  if DosError = 0 then
+  begin
+    FindClose(SRec);
+  end
+    else
+  begin
+    RaiseLastOSError;
+  end;
+end;
+
 { TIconUpdateThread }
 
 constructor TIconUpdateThread.Create(Owner: TDirView);
@@ -934,9 +953,12 @@ begin
   // do checks before passing directory to drive view, because
   // it would truncate non-existing directory to first superior existing
   Value := ReplaceStr(Value, '/', '\');
+  while ExcludeTrailingPathDelimiter(Value) <> Value do
+  begin
+    Value := ExcludeTrailingPathDelimiter(Value);
+  end;
 
-  if not DirectoryExists(ApiPath(Value)) then
-    raise Exception.CreateFmt(SDirNotExists, [Value]);
+  CheckCanOpenDirectory(Value);
 
   if Assigned(FDriveView) and
      (FDriveView.Directory <> Value) then
@@ -946,8 +968,6 @@ begin
     else
   if FPath <> Value then
   try
-    while (Length(Value) > 0) and (Value[Length(Value)] = '\') do
-      SetLength(Value, Length(Value) - 1);
     PathChanging(not FNotRelative);
     FPath := Value;
     Load(True);
@@ -2748,7 +2768,7 @@ begin
     if PFileRec(Item.Data)^.IsDirectory then
     begin
       FileName := ItemFullFileName(Item);
-      if not DirectoryExists(FileName) then
+      if not DirectoryExistsFix(FileName) then
       begin
         Reload2;
         if Assigned(FDriveView) and Assigned(FDriveView.Selected) then
@@ -2760,13 +2780,13 @@ begin
       else
     FileName := ResolveFileShortCut(ItemFullFileName(Item), True);
 
-    if DirectoryExists(FileName) then
+    if DirectoryExistsFix(FileName) then
     begin
       Path := FileName;
       Exit;
     end
       else
-    if not FileExists(ApiPath(FileName)) then
+    if not FileExistsFix(ApiPath(FileName)) then
     begin
       Exit;
     end;

+ 4 - 3
source/packages/filemng/DriveView.pas

@@ -1021,9 +1021,10 @@ begin
           Result := False;
         end
           else
-        if not DirectoryExists(ApiPath(Path)) then
-        begin
-          MessageDlg(Format(SDirNotExists, [Path]), mtError, [mbOK], 0);
+        try
+          CheckCanOpenDirectory(Path);
+        except
+          Application.HandleException(Self);
           Result := False;
         end;
       end;

+ 34 - 0
source/packages/my/PasTools.pas

@@ -79,6 +79,8 @@ procedure SetAppTerminated(Value: Boolean);
 procedure ForceColorChange(Control: TWinControl);
 
 function IsUncPath(Path: string): Boolean;
+function FileExistsFix(Path: string): Boolean;
+function DirectoryExistsFix(Path: string): Boolean;
 
 function SupportsDarkMode: Boolean;
 procedure AllowDarkModeForWindow(Control: TWinControl; Allow: Boolean); overload;
@@ -990,6 +992,38 @@ begin
   Result := (Copy(Path, 1, 2) = '\\') or (Copy(Path, 1, 2) = '//');
 end;
 
+const ERROR_CANT_ACCESS_FILE = 1920;
+
+function DoExists(R: Boolean; Path: string): Boolean;
+var
+  Error: Integer;
+begin
+  Result := R;
+  if not Result then
+  begin
+    Error := GetLastError();
+    if (Error = ERROR_CANT_ACCESS_FILE) or // returned when resolving symlinks in %LOCALAPPDATA%\Microsoft\WindowsApps
+       (Error = ERROR_ACCESS_DENIED) then // returned for %USERPROFILE%\Application Data symlink
+    begin
+      Result := DirectoryExists(ApiPath(ExtractFileDir(Path)));
+    end;
+  end;
+end;
+
+function FileExistsFix(Path: string): Boolean;
+begin
+  // WORKAROUND
+  SetLastError(ERROR_SUCCESS);
+  Result := DoExists(FileExists(ApiPath(Path)), Path);
+end;
+
+function DirectoryExistsFix(Path: string): Boolean;
+begin
+  // WORKAROUND
+  SetLastError(ERROR_SUCCESS);
+  Result := DoExists(DirectoryExists(ApiPath(Path)), Path);
+end;
+
 type TPreferredAppMode = (pamDefault, pamAllowDark, pamForceDark, pamForceLight, pamMax);
 
 var

+ 0 - 10
source/windows/GUITools.cpp

@@ -40,16 +40,6 @@
 extern const UnicodeString PageantTool = L"pageant.exe";
 extern const UnicodeString PuttygenTool = L"puttygen.exe";
 //---------------------------------------------------------------------------
-static bool __fastcall FileExistsFix(const UnicodeString & Path)
-{
-  // WORKAROUND
-  ::SetLastError(ERROR_SUCCESS);
-  return
-    FileExists(ApiPath(Path)) ||
-    // returned when resolving symlinks in %LOCALAPPDATA%\Microsoft\WindowsApps
-    (GetLastError() == ERROR_CANT_ACCESS_FILE);
-}
-//---------------------------------------------------------------------------
 bool __fastcall FindFile(UnicodeString & Path)
 {
   bool Result = FileExistsFix(Path);