ADD: Edit as admin

This commit is contained in:
Alexander Koblov 2019-10-15 18:37:17 +00:00
commit 4a18e1bf23
5 changed files with 206 additions and 169 deletions

View file

@ -3,7 +3,7 @@
-------------------------------------------------------------------------
Build-in Editor using SynEdit and his Highlighters
Copyright (C) 2006-2018 Alexander Koblov (alexx2000@mail.ru)
Copyright (C) 2006-2019 Alexander Koblov (alexx2000@mail.ru)
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@ -163,6 +163,7 @@ type
sEncodingOut,
sOriginalText: String;
FWaitData: TWaitData;
FElevate: TDuplicates;
FCommands: TFormCommands;
FMultiCaret: TSynPluginMultiCaret;
@ -237,7 +238,7 @@ implementation
uses
Clipbrd, dmCommonData, dmHigh, SynEditTypes, LCLType, LConvEncoding,
uLng, uShowMsg, fEditSearch, uGlobs, fOptions, DCClassesUtf8,
uLng, uShowMsg, fEditSearch, uGlobs, fOptions, DCClassesUtf8, uAdministrator,
uOSUtils, uConvEncoding, fOptionsToolsEditor, uDCUtils, uClipboard;
procedure ShowEditor(const sFileName: String; WaitData: TWaitData = nil);
@ -380,152 +381,168 @@ begin
end;
function TfrmEditor.OpenFile(const aFileName: String): Boolean;
var
Buffer: AnsiString;
Reader: TFileStreamEx;
Reader: TFileStreamUAC;
Highlighter: TSynCustomHighlighter;
begin
Result := False;
PushPop(FElevate);
try
Reader := TFileStreamEx.Create(aFileName, fmOpenRead or fmShareDenyNone);
Result := False;
try
SetLength(sOriginalText, Reader.Size);
Reader.Read(Pointer(sOriginalText)^, Length(sOriginalText));
finally
Reader.Free;
end;
Reader := TFileStreamUAC.Create(aFileName, fmOpenRead or fmShareDenyNone);
try
SetLength(sOriginalText, Reader.Size);
Reader.Read(Pointer(sOriginalText)^, Length(sOriginalText));
finally
Reader.Free;
end;
// Try to detect encoding by first 4 kb of text
Buffer := Copy(sOriginalText, 1, 4096);
sEncodingIn := DetectEncoding(Buffer);
ChooseEncoding(miEncodingIn, sEncodingIn);
sEncodingOut := sEncodingIn; // by default
ChooseEncoding(miEncodingOut, sEncodingOut);
// Try to detect encoding by first 4 kb of text
Buffer := Copy(sOriginalText, 1, 4096);
sEncodingIn := DetectEncoding(Buffer);
ChooseEncoding(miEncodingIn, sEncodingIn);
sEncodingOut := sEncodingIn; // by default
ChooseEncoding(miEncodingOut, sEncodingOut);
// Try to guess line break style
with Editor.Lines do
begin
if (sEncodingIn <> EncodingUTF16LE) and (sEncodingIn <> EncodingUTF16BE) then
TextLineBreakStyle := GuessLineBreakStyle(Buffer)
// Try to guess line break style
with Editor.Lines do
begin
if (sEncodingIn <> EncodingUTF16LE) and (sEncodingIn <> EncodingUTF16BE) then
TextLineBreakStyle := GuessLineBreakStyle(Buffer)
else begin
sOriginalText := Copy(sOriginalText, 3, MaxInt); // Skip BOM
TextLineBreakStyle := GuessLineBreakStyle(ConvertEncoding(Buffer, sEncodingIn, EncodingUTF8));
end;
case TextLineBreakStyle of
tlbsCRLF: actEditLineEndCrLf.Checked := True;
tlbsCR: actEditLineEndCr.Checked := True;
tlbsLF: actEditLineEndLf.Checked := True;
end;
end;
// Convert encoding if needed
if sEncodingIn = EncodingUTF8 then
Buffer := sOriginalText
else begin
sOriginalText := Copy(sOriginalText, 3, MaxInt); // Skip BOM
TextLineBreakStyle := GuessLineBreakStyle(ConvertEncoding(Buffer, sEncodingIn, EncodingUTF8));
Buffer := ConvertEncoding(sOriginalText, sEncodingIn, EncodingUTF8);
end;
case TextLineBreakStyle of
tlbsCRLF: actEditLineEndCrLf.Checked := True;
tlbsCR: actEditLineEndCr.Checked := True;
tlbsLF: actEditLineEndLf.Checked := True;
end;
// Load text into editor
Editor.Lines.Text := Buffer;
// Add empty line if needed
if (Length(Buffer) > 0) and (Buffer[Length(Buffer)] in [#10, #13]) then
Editor.Lines.Add(EmptyStr);
Result := True;
except
on E: EFCreateError do
begin
DCDebug(E.Message);
msgError(rsMsgErrECreate + ' ' + aFileName);
Exit;
end;
on E: EFOpenError do
begin
DCDebug(E.Message);
msgError(rsMsgErrEOpen + ' ' + aFileName);
Exit;
end;
on E: EReadError do
begin
DCDebug(E.Message);
msgError(rsMsgErrERead + ' ' + aFileName);
Exit;
end;
end;
// Convert encoding if needed
if sEncodingIn = EncodingUTF8 then
Buffer := sOriginalText
else begin
Buffer := ConvertEncoding(sOriginalText, sEncodingIn, EncodingUTF8);
end;
// Load text into editor
Editor.Lines.Text := Buffer;
// Add empty line if needed
if (Length(Buffer) > 0) and (Buffer[Length(Buffer)] in [#10, #13]) then
Editor.Lines.Add(EmptyStr);
Result := True;
except
on E: EFCreateError do
begin
DCDebug(E.Message);
msgError(rsMsgErrECreate + ' ' + aFileName);
Exit;
end;
on E: EFOpenError do
begin
DCDebug(E.Message);
msgError(rsMsgErrEOpen + ' ' + aFileName);
Exit;
end;
on E: EReadError do
begin
DCDebug(E.Message);
msgError(rsMsgErrERead + ' ' + aFileName);
Exit;
end;
// set up highlighter
Highlighter := dmHighl.GetHighlighter(Editor, ExtractFileExt(aFileName));
UpdateHighlighter(Highlighter);
FileName := aFileName;
bChanged := False;
bNoname := False;
UpdateStatus;
finally
PushPop(FElevate);
end;
// set up highlighter
Highlighter := dmHighl.GetHighlighter(Editor, ExtractFileExt(aFileName));
UpdateHighlighter(Highlighter);
FileName := aFileName;
bChanged := False;
bNoname := False;
UpdateStatus;
end;
function TfrmEditor.SaveFile(const aFileName: String): Boolean;
var
Mode: LongWord;
TextOut: String;
Encoding: String;
Writer: TFileStreamEx;
Writer: TFileStreamUAC;
begin
Result := False;
PushPop(FElevate);
try
Writer := TFileStreamEx.Create(aFileName, fmCreate);
Result := False;
try
Encoding := NormalizeEncoding(sEncodingOut);
// If file is empty and encoding with BOM then write only BOM
if (Editor.Lines.Count = 0) then
begin
if (Encoding = EncodingUTF8BOM) then
Writer.WriteBuffer(UTF8BOM, SizeOf(UTF8BOM))
else if (Encoding = EncodingUTF16LE) then
Writer.WriteBuffer(UTF16LEBOM, SizeOf(UTF16LEBOM))
else if (Encoding = EncodingUTF16BE) then
Writer.WriteBuffer(UTF16BEBOM, SizeOf(UTF16BEBOM));
end
if not FileExistsUAC(AFileName) then
Mode:= fmCreate
else begin
TextOut := EmptyStr;
if (Encoding = EncodingUTF16LE) then
TextOut := UTF16LEBOM
else if (Encoding = EncodingUTF16BE) then begin
TextOut := UTF16BEBOM
end;
TextOut += ConvertEncoding(Editor.Lines[0], EncodingUTF8, sEncodingOut);
Writer.WriteBuffer(Pointer(TextOut)^, Length(TextOut));
// If file has only one line then write it without line break
if Editor.Lines.Count > 1 then
begin
TextOut := TextLineBreakValue[Editor.Lines.TextLineBreakStyle];
TextOut += GetTextRange(Editor.Lines, 1, Editor.Lines.Count - 2);
// Special case for UTF-8 and UTF-8 with BOM
if (Encoding <> EncodingUTF8) and (Encoding <> EncodingUTF8BOM) then begin
TextOut:= ConvertEncoding(TextOut, EncodingUTF8, sEncodingOut);
end;
Writer.WriteBuffer(Pointer(TextOut)^, Length(TextOut));
// Write last line without line break
TextOut:= Editor.Lines[Editor.Lines.Count - 1];
// Special case for UTF-8 and UTF-8 with BOM
if (Encoding <> EncodingUTF8) and (Encoding <> EncodingUTF8BOM) then begin
TextOut:= ConvertEncoding(TextOut, EncodingUTF8, sEncodingOut);
end;
Writer.WriteBuffer(Pointer(TextOut)^, Length(TextOut));
end;
Mode:= fmOpenWrite or fmShareDenyWrite;
end;
finally
Writer.Free;
end;
Writer := TFileStreamUAC.Create(aFileName, Mode);
try
Encoding := NormalizeEncoding(sEncodingOut);
// If file is empty and encoding with BOM then write only BOM
if (Editor.Lines.Count = 0) then
begin
if (Encoding = EncodingUTF8BOM) then
Writer.WriteBuffer(UTF8BOM, SizeOf(UTF8BOM))
else if (Encoding = EncodingUTF16LE) then
Writer.WriteBuffer(UTF16LEBOM, SizeOf(UTF16LEBOM))
else if (Encoding = EncodingUTF16BE) then
Writer.WriteBuffer(UTF16BEBOM, SizeOf(UTF16BEBOM));
end
else begin
TextOut := EmptyStr;
if (Encoding = EncodingUTF16LE) then
TextOut := UTF16LEBOM
else if (Encoding = EncodingUTF16BE) then begin
TextOut := UTF16BEBOM
end;
TextOut += ConvertEncoding(Editor.Lines[0], EncodingUTF8, sEncodingOut);
Writer.WriteBuffer(Pointer(TextOut)^, Length(TextOut));
Editor.Modified := False; // needed for the undo stack
Editor.MarkTextAsSaved;
Result := True;
except
on E: Exception do
msgError(rsMsgErrSaveFile + ' ' + aFileName + LineEnding + E.Message);
// If file has only one line then write it without line break
if Editor.Lines.Count > 1 then
begin
TextOut := TextLineBreakValue[Editor.Lines.TextLineBreakStyle];
TextOut += GetTextRange(Editor.Lines, 1, Editor.Lines.Count - 2);
// Special case for UTF-8 and UTF-8 with BOM
if (Encoding <> EncodingUTF8) and (Encoding <> EncodingUTF8BOM) then begin
TextOut:= ConvertEncoding(TextOut, EncodingUTF8, sEncodingOut);
end;
Writer.WriteBuffer(Pointer(TextOut)^, Length(TextOut));
// Write last line without line break
TextOut:= Editor.Lines[Editor.Lines.Count - 1];
// Special case for UTF-8 and UTF-8 with BOM
if (Encoding <> EncodingUTF8) and (Encoding <> EncodingUTF8BOM) then begin
TextOut:= ConvertEncoding(TextOut, EncodingUTF8, sEncodingOut);
end;
Writer.WriteBuffer(Pointer(TextOut)^, Length(TextOut));
end;
end;
if (Mode <> fmCreate) then Writer.Size:= Writer.Position;
finally
Writer.Free;
end;
Editor.Modified := False; // needed for the undo stack
Editor.MarkTextAsSaved;
Result := True;
except
on E: Exception do
msgError(rsMsgErrSaveFile + ' ' + aFileName + LineEnding + E.Message);
end;
finally
PushPop(FElevate);
end;
end;

View file

@ -60,6 +60,7 @@ end;
procedure TfrmHardLink.btnOKClick(Sender: TObject);
var
sSrc, sDst, Message: String;
AElevate: TDuplicates = dupIgnore;
begin
sSrc:=edtExistingFile.Text;
sDst:=edtLinkToCreate.Text;
@ -69,23 +70,26 @@ begin
sSrc := GetAbsoluteFileName(FCurrentPath, sSrc);
sDst := GetAbsoluteFileName(FCurrentPath, sDst);
ElevateAction:= dupIgnore;
if CreateHardLinkUAC(sSrc, sDst) then
begin
// write log
if (log_cp_mv_ln in gLogOptions) and (log_success in gLogOptions) then
logWrite(Format(rsMsgLogSuccess+rsMsgLogLink,[sSrc+' -> '+sDst]), lmtSuccess);
end
else
begin
Message:= mbSysErrorMessage;
// write log
if (log_cp_mv_ln in gLogOptions) and (log_errors in gLogOptions) then
logWrite(Format(rsMsgLogError+rsMsgLogLink,[sSrc+' -> '+sDst]), lmtError);
// Standart error modal dialog
MsgError(rsHardErrCreate + LineEnding + LineEnding + Message);
end;
PushPop(AElevate);
try
if CreateHardLinkUAC(sSrc, sDst) then
begin
// write log
if (log_cp_mv_ln in gLogOptions) and (log_success in gLogOptions) then
logWrite(Format(rsMsgLogSuccess+rsMsgLogLink,[sSrc+' -> '+sDst]), lmtSuccess);
end
else
begin
Message:= mbSysErrorMessage;
// write log
if (log_cp_mv_ln in gLogOptions) and (log_errors in gLogOptions) then
logWrite(Format(rsMsgLogError+rsMsgLogLink,[sSrc+' -> '+sDst]), lmtError);
// Standart error modal dialog
MsgError(rsHardErrCreate + LineEnding + LineEnding + Message);
end;
finally
PushPop(AElevate);
end;
end;
procedure TfrmHardLink.FormShow(Sender: TObject);

View file

@ -61,6 +61,7 @@ end;
procedure TfrmSymLink.btnOKClick(Sender: TObject);
var
sSrc, sDst, Message: String;
AElevate: TDuplicates = dupIgnore;
begin
sSrc:=edtExistingFile.Text;
sDst:=edtLinkToCreate.Text;
@ -73,23 +74,26 @@ begin
sSrc:= CreateRelativePath(sSrc, ExtractFileDir(sDst));
end;
ElevateAction:= dupIgnore;
if CreateSymbolicLinkUAC(sSrc, sDst) then
begin
// write log
if (log_cp_mv_ln in gLogOptions) and (log_success in gLogOptions) then
logWrite(Format(rsMsgLogSuccess+rsMsgLogSymLink,[sSrc+' -> '+sDst]), lmtSuccess);
end
else
begin
Message:= mbSysErrorMessage;
// write log
if (log_cp_mv_ln in gLogOptions) and (log_errors in gLogOptions) then
logWrite(Format(rsMsgLogError+rsMsgLogSymLink,[sSrc+' -> '+sDst]), lmtError);
// Standart error modal dialog
MsgError(rsSymErrCreate + LineEnding + LineEnding + Message);
end;
PushPop(AElevate);
try
if CreateSymbolicLinkUAC(sSrc, sDst) then
begin
// write log
if (log_cp_mv_ln in gLogOptions) and (log_success in gLogOptions) then
logWrite(Format(rsMsgLogSuccess+rsMsgLogSymLink,[sSrc+' -> '+sDst]), lmtSuccess);
end
else
begin
Message:= mbSysErrorMessage;
// write log
if (log_cp_mv_ln in gLogOptions) and (log_errors in gLogOptions) then
logWrite(Format(rsMsgLogError+rsMsgLogSymLink,[sSrc+' -> '+sDst]), lmtError);
// Standart error modal dialog
MsgError(rsSymErrCreate + LineEnding + LineEnding + Message);
end;
finally
PushPop(AElevate);
end;
end;
procedure TfrmSymLink.FormShow(Sender: TObject);

View file

@ -7,6 +7,8 @@ interface
uses
Classes, SysUtils, DCBasicTypes, DCClassesUtf8;
procedure PushPop(var Elevate: TDuplicates);
function FileExistsUAC(const FileName: String): Boolean;
function FileGetAttrUAC(const FileName: String): TFileAttrs;
function FileSetAttrUAC(const FileName: String; Attr: TFileAttrs): Boolean;
@ -76,6 +78,15 @@ resourcestring
rsElevationRequiredGetAttributes = 'to get attributes of this object:';
rsElevationRequiredSetAttributes = 'to set attributes of this object:';
procedure PushPop(var Elevate: TDuplicates);
var
AValue: TDuplicates;
begin
AValue:= ElevateAction;
ElevateAction:= Elevate;
Elevate:= AValue;
end;
function RequestElevation(const Message, FileName: String): Boolean;
var
Text: String;
@ -418,16 +429,11 @@ begin
end;
fsFileStream:= TFileStreamUAC.Create(FileName, AMode);
try
if (AMode <> fmCreate) then
begin
fsFileStream.Position:= 0;
fsFileStream.Size:= 0;
end;
SaveToStream(fsFileStream);
if (AMode <> fmCreate) then fsFileStream.Size:= fsFileStream.Position;
finally
fsFileStream.Free;
end;
end;
end.

View file

@ -390,7 +390,7 @@ uses fOptionsPluginsBase, fOptionsPluginsDSX, fOptionsPluginsWCX,
DCOSUtils, DCStrUtils, DCBasicTypes, uFileSourceCopyOperation, fSyncDirsDlg,
uHotDir, DCXmlConfig, dmCommonData, fOptionsFrame, foptionsDirectoryHotlist,
fMainCommandsDlg, uConnectionManager, fOptionsFavoriteTabs, fTreeViewMenu,
uArchiveFileSource, fOptionsHotKeys, fBenchmark
uArchiveFileSource, fOptionsHotKeys, fBenchmark, uAdministrator
{$IFDEF COLUMNSFILEVIEW_VTV}
, uColumnsFileViewVtv
{$ELSE}
@ -3529,6 +3529,7 @@ var
sCmd: string = '';
sParams: string = '';
sStartPath: string = '';
AElevate: TDuplicates = dupIgnore;
begin
frmMain.ActiveFrame.ExecuteCommand('cm_EditNew', Params);
@ -3554,23 +3555,28 @@ begin
if ExtractFilePath(sNewFile) = '' then
sNewFile:= ActiveFrame.CurrentPath + sNewFile;
Attrs := mbFileGetAttr(sNewFile);
if Attrs = faInvalidAttributes then
begin
hFile := mbFileCreate(sNewFile);
if hFile = feInvalidHandle then
PushPop(AElevate);
try
Attrs := FileGetAttrUAC(sNewFile);
if Attrs = faInvalidAttributes then
begin
MessageDlg(rsMsgErrECreate, mbSysErrorMessage(GetLastOSError), mtWarning, [mbOK], 0);
hFile := FileCreateUAC(sNewFile, fmShareDenyWrite);
if hFile = feInvalidHandle then
begin
MessageDlg(rsMsgErrECreate, mbSysErrorMessage(GetLastOSError), mtWarning, [mbOK], 0);
Exit;
end;
FileClose(hFile);
ActiveFrame.FileSource.Reload(ExtractFilePath(sNewFile));
end
else if FPS_ISDIR(Attrs) then
begin
MessageDlg(rsMsgErrECreate, Format(rsMsgErrCreateFileDirectoryExists,
[ExtractFileName(sNewFile)]), mtWarning, [mbOK], 0);
Exit;
end;
FileClose(hFile);
ActiveFrame.FileSource.Reload(ExtractFilePath(sNewFile));
end
else if FPS_ISDIR(Attrs) then
begin
MessageDlg(rsMsgErrECreate, Format(rsMsgErrCreateFileDirectoryExists,
[ExtractFileName(sNewFile)]), mtWarning, [mbOK], 0);
Exit;
finally
PushPop(AElevate);
end;
aFile := TFileSystemFileSource.CreateFileFromFile(sNewFile);