ADD: Elevate CreateDirectory, CreateHardLink nad CreateSymbolicLink

This commit is contained in:
Alexander Koblov 2019-09-18 16:44:14 +00:00
commit 204ca8efd0
6 changed files with 78 additions and 8 deletions

View file

@ -34,7 +34,7 @@ implementation
{$R *.lfm}
uses
LazFileUtils, uLng, uGlobs, uLog, uShowMsg, uOSUtils, DCStrUtils, DCOSUtils;
LazFileUtils, uLng, uGlobs, uLog, uShowMsg, DCStrUtils, DCOSUtils, uAdministrator;
function ShowHardLinkForm(const sExistingFile, sLinkToCreate, CurrentPath: String): Boolean;
begin
@ -69,7 +69,7 @@ begin
sSrc := GetAbsoluteFileName(FCurrentPath, sSrc);
sDst := GetAbsoluteFileName(FCurrentPath, sDst);
if CreateHardLink(sSrc, sDst) then
if CreateHardLinkUAC(sSrc, sDst) then
begin
// write log
if (log_cp_mv_ln in gLogOptions) and (log_success in gLogOptions) then

View file

@ -27,7 +27,7 @@ type
implementation
uses
uFileSourceOperationUI, uFileProcs, uLog, uLng, uGlobs, DCOSUtils;
uFileSourceOperationUI, uLog, uLng, uGlobs, DCOSUtils, uAdministrator;
constructor TFileSystemCreateDirectoryOperation.Create(
aTargetFileSource: IFileSource;
@ -44,11 +44,11 @@ end;
procedure TFileSystemCreateDirectoryOperation.MainExecute;
begin
if mbFileGetAttr(AbsolutePath) <> faInvalidAttributes then
if FileGetAttrUAC(AbsolutePath) <> faInvalidAttributes then
begin
AskQuestion(Format(rsMsgErrDirExists, [AbsolutePath]), '', [fsourOk], fsourOk, fsourOk);
end
else if uFileProcs.mbForceDirectory(AbsolutePath) = False then
else if ForceDirectoriesUAC(AbsolutePath) = False then
begin
if (log_dir_op in gLogOptions) and (log_errors in gLogOptions) then
logWrite(Thread, Format(rsMsgLogError+rsMsgLogMkDir, [AbsolutePath]), lmtError);

View file

@ -35,7 +35,7 @@ implementation
{$R *.lfm}
uses
LazFileUtils, uLng, uGlobs, uLog, uShowMsg, uOSUtils, DCStrUtils, DCOSUtils;
LazFileUtils, uLng, uGlobs, uLog, uShowMsg, DCStrUtils, DCOSUtils, uAdministrator;
function ShowSymLinkForm(const sExistingFile, sLinkToCreate, CurrentPath: String): Boolean;
begin
@ -73,7 +73,7 @@ begin
sSrc:= CreateRelativePath(sSrc, ExtractFileDir(sDst));
end;
if CreateSymLink(sSrc, sDst) then
if CreateSymbolicLinkUAC(sSrc, sDst) then
begin
// write log
if (log_cp_mv_ln in gLogOptions) and (log_success in gLogOptions) then

View file

@ -21,8 +21,10 @@ function FileCreateUAC(const FileName: String; Mode: LongWord): System.THandle;
function DeleteFileUAC(const FileName: String): LongBool;
function RenameFileUAC(const OldName, NewName: String): LongBool;
function ForceDirectoriesUAC(const Path: String): Boolean;
function CreateDirectoryUAC(const Directory: String): Boolean;
function RemoveDirectoryUAC(const Directory: String): Boolean;
function DirectoryExistsUAC(const Directory : String): Boolean;
function CreateSymbolicLinkUAC(const Path, LinkName: String) : Boolean;
function CreateHardLinkUAC(const Path, LinkName: String) : Boolean;
@ -51,7 +53,8 @@ threadvar
implementation
uses
RtlConsts, DCOSUtils, LCLType, uShowMsg, uElevation, uSuperUser, fElevation;
RtlConsts, DCStrUtils, DCOSUtils, LCLType, uShowMsg, uElevation, uSuperUser,
fElevation;
resourcestring
rsElevationRequired = 'You need to provide administrator permission';
@ -234,6 +237,21 @@ begin
end;
end;
function DirectoryExistsUAC(const Directory: String): Boolean;
var
LastError: Integer;
begin
Result:= mbDirectoryExists(Directory);
if (not Result) and ElevationRequired then
begin
LastError:= GetLastOSError;
if RequestElevation(rsElevationRequiredGetAttributes, Directory) then
Result:= TWorkerProxy.Instance.DirectoryExists(Directory)
else
SetLastOSError(LastError);
end;
end;
function CreateHardLinkUAC(const Path, LinkName: String): Boolean;
var
LastError: Integer;
@ -264,6 +282,42 @@ begin
end;
end;
function ForceDirectoriesUAC(const Path: String): Boolean;
var
Index: Integer;
ADirectory: String;
ADirectoryPath: String;
begin
if Path = '' then Exit;
ADirectoryPath := IncludeTrailingPathDelimiter(Path);
Index:= 1;
if Pos('\\', ADirectoryPath) = 1 then // if network path
begin
Index := CharPos(PathDelim, ADirectoryPath, 3); // index of the end of computer name
Index := CharPos(PathDelim, ADirectoryPath, Index + 1); // index of the end of first remote directory
end;
// Move past path delimiter at the beginning.
if (Index = 1) and (ADirectoryPath[Index] = PathDelim) then
Index := Index + 1;
while Index <= Length(ADirectoryPath) do
begin
if ADirectoryPath[Index] = PathDelim then
begin
ADirectory:= Copy(ADirectoryPath, 1, Index - 1);
if not DirectoryExistsUAC(ADirectory) then
begin
Result:= CreateDirectoryUAC(ADirectory);
if not Result then Exit;
end;
end;
Inc(Index);
end;
Result := True;
end;
{ TFileStreamUAC }
procedure TFileStreamUAC.SetSize64(const NewSize: Int64);

View file

@ -48,6 +48,7 @@ type
function CreateSymbolicLink(const Path, LinkName: String): LongBool; inline;
function CreateDirectory(const Directory: String): LongBool; inline;
function RemoveDirectory(const Directory: String): LongBool; inline;
function DirectoryExists(const Directory: String): LongBool; inline;
public
constructor Create;
destructor Destroy; override;
@ -411,6 +412,11 @@ begin
Result:= ProcessObject(RPC_RemoveDirectory, Directory);
end;
function TWorkerProxy.DirectoryExists(const Directory: String): LongBool;
begin
Result:= ProcessObject(RPC_DirectoryExists, Directory);
end;
constructor TWorkerProxy.Create;
begin
FClient:= TPipeTransport.Create(WorkerAddress + IntToStr(GetProcessID));

View file

@ -39,6 +39,7 @@ const
RPC_CreateDirectory = 5;
RPC_RemoveDirectory = 6;
RPC_DirectoryExists = 13;
type
@ -218,6 +219,15 @@ begin
ATransport.WriteBuffer(Result, SizeOf(Result));
ATransport.WriteBuffer(LastError, SizeOf(LastError));
end;
RPC_DirectoryExists:
begin
FileName:= ARequest.ReadAnsiString;
DCDebug('DirectoryExists ', FileName);
Result:= mbDirectoryExists(FileName);
LastError:= GetLastOSError;
ATransport.WriteBuffer(Result, SizeOf(Result));
ATransport.WriteBuffer(LastError, SizeOf(LastError));
end;
RPC_Terminate: Halt;
end;
end;