ADD: FileSetReadOnlyUAC function

This commit is contained in:
Alexander Koblov 2019-10-12 12:14:52 +00:00
commit a75531f304
6 changed files with 82 additions and 45 deletions

View file

@ -141,7 +141,7 @@ function mbFileSetTime(const FileName: String;
function mbFileExists(const FileName: String): Boolean;
function mbFileAccess(const FileName: String; Mode: Word): Boolean;
function mbFileGetAttr(const FileName: String): TFileAttrs; overload;
function mbFileSetAttr(const FileName: String; Attr: TFileAttrs) : LongInt;
function mbFileSetAttr(const FileName: String; Attr: TFileAttrs): Boolean;
{en
If any operation in Options is performed and does not succeed it is included
in the result set. If all performed operations succeed the function returns empty set.
@ -371,7 +371,7 @@ begin
begin
if (caoRemoveReadOnlyAttr in Options) and ((Attr and faReadOnly) <> 0) then
Attr := (Attr and not faReadOnly);
if mbFileSetAttr(sDst, Attr) <> 0 then
if not mbFileSetAttr(sDst, Attr) then
Include(Result, caoCopyAttributes);
end
else
@ -899,17 +899,14 @@ begin
end;
{$ENDIF}
function mbFileSetAttr(const FileName: String; Attr: TFileAttrs): LongInt;
function mbFileSetAttr(const FileName: String; Attr: TFileAttrs): Boolean;
{$IFDEF MSWINDOWS}
begin
if SetFileAttributesW(PWideChar(UTF16LongName(FileName)), Attr) then
Result:= 0
else
Result:= GetLastError;
Result:= SetFileAttributesW(PWideChar(UTF16LongName(FileName)), Attr);
end;
{$ELSE}
begin
Result:= fpchmod(UTF8ToSys(FileName), Attr);
Result:= fpchmod(UTF8ToSys(FileName), Attr) = 0;
end;
{$ENDIF}

View file

@ -213,7 +213,7 @@ begin
if (FRecycle = False) then
begin
if FileIsReadOnly(aFile.Attributes) then
mbFileSetReadOnly(FileName, False);
FileSetReadOnlyUAC(FileName, False);
if aFile.IsDirectory then // directory
begin

View file

@ -180,9 +180,9 @@ begin
if (aTemplateProperty as TFileAttributesProperty).Value <>
(aFile.Properties[fpAttributes] as TFileAttributesProperty).Value then
begin
if FileSetAttrUAC(
if not FileSetAttrUAC(
aFile.FullPath,
(aTemplateProperty as TFileAttributesProperty).Value) <> 0 then
(aTemplateProperty as TFileAttributesProperty).Value) then
begin
Result := sfprError;
end;

View file

@ -9,11 +9,12 @@ uses
function FileExistsUAC(const FileName: String): Boolean;
function FileGetAttrUAC(const FileName: String): TFileAttrs;
function FileSetAttrUAC(const FileName: String; Attr: TFileAttrs): Integer;
function FileSetAttrUAC(const FileName: String; Attr: TFileAttrs): Boolean;
function FileSetTimeUAC(const FileName: String;
ModificationTime: DCBasicTypes.TFileTime;
CreationTime : DCBasicTypes.TFileTime = 0;
LastAccessTime : DCBasicTypes.TFileTime = 0): LongBool;
function FileSetReadOnlyUAC(const FileName: String; ReadOnly: Boolean): Boolean;
function FileOpenUAC(const FileName: String; Mode: LongWord): System.THandle;
function FileCreateUAC(const FileName: String; Mode: LongWord): System.THandle;
@ -125,12 +126,12 @@ begin
end;
end;
function FileSetAttrUAC(const FileName: String; Attr: TFileAttrs): Integer;
function FileSetAttrUAC(const FileName: String; Attr: TFileAttrs): Boolean;
var
LastError: Integer;
begin
Result:= mbFileSetAttr(FileName, Attr);
if (Result <> 0) and ElevationRequired then
if (not Result) and ElevationRequired then
begin
LastError:= GetLastOSError;
if RequestElevation(rsElevationRequiredSetAttributes, FileName) then
@ -158,6 +159,21 @@ begin
end;
end;
function FileSetReadOnlyUAC(const FileName: String; ReadOnly: Boolean): Boolean;
var
LastError: Integer;
begin
Result:= mbFileSetReadOnly(FileName, ReadOnly);
if (not Result) and ElevationRequired then
begin
LastError:= GetLastOSError;
if RequestElevation(rsElevationRequiredSetAttributes, FileName) then
Result:= TWorkerProxy.Instance.FileSetReadOnly(FileName, ReadOnly)
else
SetLastOSError(LastError);
end;
end;
function FileOpenUAC(const FileName: String; Mode: LongWord): System.THandle;
var
LastError: Integer;

View file

@ -30,16 +30,18 @@ type
FClient: TBaseTransport;
function ProcessObject(ACommand: UInt32; const ObjectName: String): LongBool;
function ProcessObject(ACommand: UInt32; const OldName, NewName: String): LongBool;
function ProcessObject(ACommand: UInt32; const ObjectName: String; Attr: UInt32): LongBool;
function ProcessObject(ACommand: UInt32; const ObjectName: String; Mode: Integer): THandle;
public
function Terminate: Boolean;
function FileExists(const FileName: String): LongBool; inline;
function FileGetAttr(const FileName: String): TFileAttrs; inline;
function FileSetAttr(const FileName: String; Attr: TFileAttrs): Integer;
function FileSetAttr(const FileName: String; Attr: TFileAttrs): LongBool; inline;
function FileSetTime(const FileName: String;
ModificationTime: DCBasicTypes.TFileTime;
CreationTime : DCBasicTypes.TFileTime;
LastAccessTime : DCBasicTypes.TFileTime): LongBool;
function FileSetReadOnly(const FileName: String; ReadOnly: Boolean): LongBool; inline;
function FileOpen(const FileName: String; Mode: Integer): THandle; inline;
function FileCreate(const FileName: String; Mode: Integer): THandle; inline;
function DeleteFile(const FileName: String): LongBool; inline;
@ -238,6 +240,39 @@ begin
end;
end;
function TWorkerProxy.ProcessObject(ACommand: UInt32; const ObjectName: String;
Attr: UInt32): LongBool;
var
LastError: Integer;
Stream: TMemoryStream;
begin
Result:= False;
try
Stream:= TMemoryStream.Create;
try
// Write header
Stream.WriteDWord(ACommand);
Stream.Seek(SizeOf(UInt32), soFromCurrent);
// Write arguments
Stream.WriteAnsiString(ObjectName);
Stream.WriteDWord(Attr);
// Write data size
Stream.Seek(SizeOf(UInt32), soFromBeginning);
Stream.WriteDWord(Stream.Size - SizeOf(UInt32) * 2);
// Send command
FClient.WriteBuffer(Stream.Memory^, Stream.Size);
// Receive command result
FClient.ReadBuffer(Result, SizeOf(Result));
FClient.ReadBuffer(LastError, SizeOf(LastError));
SetLastOSError(LastError);
finally
Stream.Free;
end;
except
on E: Exception do DCDebug(E.Message);
end;
end;
function TWorkerProxy.ProcessObject(ACommand: UInt32; const ObjectName: String;
Mode: Integer): THandle;
var
@ -303,36 +338,9 @@ begin
Result:= TFileAttrs(ProcessObject(RPC_FileGetAttr, FileName));
end;
function TWorkerProxy.FileSetAttr(const FileName: String; Attr: TFileAttrs): Integer;
var
LastError: Integer;
Stream: TMemoryStream;
function TWorkerProxy.FileSetAttr(const FileName: String; Attr: TFileAttrs): LongBool;
begin
Result:= -1;
try
Stream:= TMemoryStream.Create;
try
// Write header
Stream.WriteDWord(RPC_FileSetAttr);
Stream.Seek(SizeOf(UInt32), soFromCurrent);
// Write arguments
Stream.WriteAnsiString(FileName);
Stream.WriteDWord(Attr);
// Write data size
Stream.Seek(SizeOf(UInt32), soFromBeginning);
Stream.WriteDWord(Stream.Size - SizeOf(UInt32) * 2);
// Send command
FClient.WriteBuffer(Stream.Memory^, Stream.Size);
// Receive command result
FClient.ReadBuffer(Result, SizeOf(Result));
FClient.ReadBuffer(LastError, SizeOf(LastError));
SetLastOSError(LastError);
finally
Stream.Free;
end;
except
on E: Exception do DCDebug(E.Message);
end;
Result:= ProcessObject(RPC_FileSetAttr, FileName, Attr);
end;
function TWorkerProxy.FileSetTime(const FileName: String;
@ -372,6 +380,11 @@ begin
end;
end;
function TWorkerProxy.FileSetReadOnly(const FileName: String; ReadOnly: Boolean): LongBool;
begin
Result:= ProcessObject(RPC_FileSetReadOnly, FileName, UInt32(ReadOnly));
end;
function TWorkerProxy.FileOpen(const FileName: String; Mode: Integer): THandle;
begin
Result:= ProcessObject(RPC_FileOpen, FileName, Mode);

View file

@ -30,6 +30,7 @@ const
RPC_FileGetAttr = 10;
RPC_FileSetAttr = 11;
RPC_FileSetTime = 12;
RPC_FileSetReadOnly = 14;
RPC_CreateHardLink = 8;
RPC_CreateSymbolicLink = 7;
@ -134,7 +135,7 @@ begin
FileName:= ARequest.ReadAnsiString;
Attr:= ARequest.ReadDWord;
DCDebug('FileSetAttr ', FileName);
Result:= LongBool(mbFileSetAttr(FileName, Attr));
Result:= mbFileSetAttr(FileName, Attr);
LastError:= GetLastOSError;
ATransport.WriteBuffer(Result, SizeOf(Result));
ATransport.WriteBuffer(LastError, SizeOf(LastError));
@ -151,6 +152,16 @@ begin
ATransport.WriteBuffer(Result, SizeOf(Result));
ATransport.WriteBuffer(LastError, SizeOf(LastError));
end;
RPC_FileSetReadOnly:
begin
FileName:= ARequest.ReadAnsiString;
Attr:= ARequest.ReadDWord;
DCDebug('FileSetReadOnly ', FileName);
Result:= mbFileSetReadOnly(FileName, Boolean(Attr));
LastError:= GetLastOSError;
ATransport.WriteBuffer(Result, SizeOf(Result));
ATransport.WriteBuffer(LastError, SizeOf(LastError));
end;
RPC_FileOpen:
begin
FileName:= ARequest.ReadAnsiString;