BSOne.SFC/eCrmHE/EXE_eCrmHomeEdition/Service/RecoverService.pas

903 lines
30 KiB
Plaintext

{*******************************************************}
{ }
{ RecoverService }
{ }
{ Copyright (C) 2022 kku }
{ }
{*******************************************************}
unit RecoverService;
interface
uses
System.SysUtils, System.Classes,System.JSON,System.IOUtils,System.Hash,
Vcl.Graphics, Tocsg.Thread, ManagerPattern, Tocsg.Files,
System.Generics.Collections;
const
KVBIN_FILES = 'afsr.dll|aiffsr.dll|asfsr.dll|assr.dll|awsr.dll|bentofio.dll|' +
'bkfsr.dll|bmpsr.dll|bzip2sr.dll|cabsr.dll|cbmap.map|chartbls.ux|' +
'csvsr.dll|dbxsr.dll|dcasr.dll|dcmsr.dll|difsr.dll|dmgsr.dll|' +
'dw4sr.dll|dxlsr.dll|emlsr.dll|emxsr.dll|encasesr.dll|entsr.dll|' +
'epubsr.dll|filter.exe|FilterDotNet.dll|filterfordotnet.dll|' +
'FilterTestDotNet.exe|foliosr.dll|formats.ini|gifsr.dll|' +
'hl7sr.dll|htmsr.dll|hwposr.dll|hwpsr.dll|ichatsr.dll|isosr.dll|' +
'iwsssr.dll|iwwpsr.dll|jpgsr.dll|jtdsr.dll|KeyViewFilter.dll|' +
'kpagrdr.dll|kpcatrdr.dll|kpdwgrdr.dll|kpdxfrdr.dll|kpemfrdr.dll|' +
'kpgflrdr.dll|kpgifrdr.dll|kpifcnvt.dll|kpifutil.dll|kpiwpgrdr.dll|' +
'kpmsordr.dll|kpodfrdr.dll|kpp40rdr.dll|kpp95rdr.dll|kpp97rdr.dll|' +
'kppctrdr.dll|kppicrdr.dll|kppng.dll|kpppxrdr.dll|kpprerdr.dll|' +
'kpprzrdr.dll|kpsdwrdr.dll|kpshwrdr.dll|kpwg2rdr.dll|kpwmfrdr.dll|' +
'kpwpgrdr.dll|kpxfdlrdr.dll|kv.lic|kvdecrypt.dll|kvfilter.dll|' +
'kvgzsr.dll|kvhqxsr.dll|kvhvp.dll|kvlangdetect.dll|kvolefio.dll|' +
'kvoop.exe|kvutil.dll|kvxconfig.ini|kvxpgsa.dll|kvxsssa.dll|' +
'kvxtract.dll|kvxwpsa.dll|kvzeesr.dll|kvzip.dll|kwad.dll|l123sr.dll|' +
'langdetectext.dll|lasr.dll|libpff.dll|license.ini|lzhsr.dll|' +
'macbinsr.dll|mbsr.dll|mbxsr.dll|mdbsr.dll|mhtsr.dll|Microsoft.VC80.CRT.manifest|' +
'mifsr.dll|misr.dll|mp3sr.dll|mpeg4sr.dll|mppsr.dll|msgsr.dll|' +
'msvcm80.dll|msvcp80.dll|msvcr80.dll|msw6sr.dll|mswsr.dll|mw6sr.dll|' +
'mw8sr.dll|mwsr.dll|mwssr.dll|mwxsr.dll|oa2sr.dll|odfsssr.dll|' +
'odfwpsr.dll|olesr.dll|onmsr.dll|oo3sr.dll|pdfsr.dll|pffsr.dll|' +
'pngsr.dll|pstnsr.dll|qpssr.dll|qpwsr.dll|rarsr.dll|riffsr.dll|' +
'rtfsr.dll|skypesr.dll|sosr.dll|sunadsr.dll|swfsr.dll|tarsr.dll|' +
'tifsr.dll|tnefsr.dll|tstxtract.exe|txtcnv.dll|unisr.dll|unzip.dll|' +
'utf8sr.dll|uudsr.dll|vsdsr.dll|wkssr.dll|wosr.dll|wp6sr.dll|' +
'wpmap.dll|wpmsr.dll|xlsbsr.dll|xlssr.dll|xlsxsr.dll|xmlsh.dll|' +
'xmlsr.dll|xpssr.dll|xywsr.dll|yimsr.dll|z7zsr.dll|langdetect.dat|' +
'TB_arabic_mac_ucs2.txt|TB_arabic_ucs2.txt|TB_ascii_ibm_ucs2.txt|' +
'TB_ascii_ucs2.txt|TB_chsimplified_ucs2.txt|TB_chtraditional_chsimplified.txt|' +
'TB_chtraditional_ucs2.txt|TB_cyrillicdos_ucs2.txt|TB_cyrillickoi8_ucs2.txt|' +
'TB_cyrillic_ucs2.txt|TB_easterneuropean_ucs2.txt|TB_greek_ucs2.txt|' +
'TB_hebrew_ucs2.txt|TB_iso8859.txt|TB_korean_ucs2.txt|TB_latin3_ucs2.txt|' +
'TB_latin5_ucs2.txt|TB_latin6_ucs2.txt|TB_latin7_ucs2.txt|TB_latin9_ucs2.txt|' +
'TB_northerneuropean_ucs2.txt|TB_shiftjis_ucs2.txt|TB_thai_ucs2.txt|' +
'TB_turkish_ucs2.txt|TB_ucs2chsimp_ucs2chtrad.txt|TB_ucs2chtrad_ucs2chsimp.txt|' +
'TB_unicode_entities.txt|TB_vietnamese_ucs2.txt|TB_westerneuropean_ucs2.txt|' +
'text_arabic_iso.txt|text_arabic_ucs2.txt|text_arabic_utf8.txt|' +
'text_arabic_win.txt|text_ascii.txt|text_ascii_ucs2.txt|text_ascii_utf8.txt|' +
'text_chsimplified.txt|text_chsimplified_ucs2.txt|text_chsimplified_utf8.txt|' +
'text_chtraditional.txt|text_chtraditional_chsimplified.keyview.txt|' +
'text_chtraditional_inv.txt|text_chtraditional_ucs2.keyview.txt|' +
'text_chtraditional_ucs2.txt|text_chtraditional_utf8.keyview.txt|' +
'text_chtraditional_utf8.txt|text_cyrillic_dos.txt|text_cyrillic_iso.txt|' +
'text_cyrillic_koi8.txt|text_cyrillic_ucs2.txt|text_cyrillic_utf8.txt|' +
'text_cyrillic_win.txt|text_easterneuropean_iso.txt|text_easterneuropean_ucs2.txt|' +
'text_easterneuropean_utf8.txt|text_easterneuropean_win.txt|text_euc.txt|' +
'text_greek_iso.txt|text_greek_ucs2.txt|text_greek_utf8.txt|text_greek_win.txt|' +
'text_hebrew_iso.txt|text_hebrew_ucs2.txt|text_hebrew_utf8.txt|' +
'text_hebrew_win.txt|text_jis.txt|text_jis_1.txt|text_katakana_shiftjis.txt|' +
'text_katakana_ucs2.txt|text_katakana_utf8.txt|text_korean.txt|text_korean_ucs2.txt|' +
'text_korean_utf8.txt|text_maori.ne.txt|text_maori.txt|text_maori_ucs2.txt|' +
'text_maori_utf8.txt|text_northerneuropean_iso.txt|text_northerneuropean_ucs2.txt|' +
'text_northerneuropean_utf8.txt|text_northerneuropean_win.txt|text_shiftjis.txt|' +
'text_shiftjis_ucs2.txt|text_shiftjis_utf8.txt|text_thai.txt|text_thai_ucs2.txt|' +
'text_thai_utf8.txt|text_turkish.txt|text_turkish_ucs2.txt|text_turkish_utf8.txt|' +
'text_utf8_1.keyview.txt|text_utf8_1.txt|text_utf8_1_to_jis.keyview.txt|' +
'text_utf8_1_to_jis.txt|text_vietnamese_ucs2.txt|text_vietnamese_utf8.txt|' +
'text_vietnamese_win.txt|text_westerneuropean.txt|text_westerneuropean_utf8.txt|';
CONF_FILES = 'eCrmHeHelper.dll|eCrmHeHelper.exe|eCrmHeHelper32.dll|eCrmInterCaller.exe|' +
'BSWmcr.exe|Bs1out.dll|Bs1out64.dll|Bs1shl.dll|Bs1uef.dat|Bs1tri.dat';
HEBIN_FILES = 'eCrmHomeEdition.exe|ielib64.dll|KvCttSch.exe|KvCttSchw.exe|libeay32.dll|' +
'libkm64.dll|ptnsch.dat|ssleay32.dll|bs1flt_x64.sys|bs1fltctrl.dll|bsonex32.sys|bsonex64.sys';
LANG_FILES = 'eCrmHomeEdition.409.dat|eCrmHomeEdition.412.dat|eCrmHomeEdition.411.dat|' +
'eCrmHomeEdition.804.dat|eCrmHomeEdition.404.dat';
SLCORE_FILES = 'slcore.exe';
SLCORE_DATA_FILES = 'SLT@|sltgd.dat';
DATA_FILES = 'pdmsa.prop|admsa.prop|cdmsa.prop|csmsa.pro'; // cfmsa.prop 사용하지 않음
DIR_NAMES = 'bin|conf|Data|Language|Resource';
type
TRecoverService = class(TTgDirWatchBase)
private
DataFiles_,
DirNames_,
KvBinFiles_,
HeBinFiles_,
ConfFiles_,
LangFiles_,
SLCoreDatas_,
SLCoreFiles_: TStringList;
LockFiles_: TList<TFileStream>;
bIsWorking_: Boolean;
bBlockRename_: Boolean;
sBlkFRename_,
sIgrBlkFRename_: String;
bRecovering_: Boolean;
referenceData_: TDictionary<string, string>;
procedure OnLockFileNotify(Sender: TObject; const Item: TFileStream; Action: TCollectionNotification);
procedure ProcessDirWatchEnt(Sender: TObject; pInfo: PDirWatchEnt); override;
procedure LockFiles;
procedure UnlockFiles;
procedure RecoverAll;
procedure RecoverData;
procedure LoadReferenceJson(const JsonPath: string);
function CheckFileIntegrity(const FilePath, ExpectedHash: string;
out ActualHash, Reason: string): Boolean;
procedure CheckAndRecover(sResPath, sPath: String);
function DoRecoverFile(const sTargetFilePath: string): string;
public
Constructor Create;
Destructor Destroy; override;
procedure StartService;
procedure StopService;
property IsWorking: Boolean read bIsWorking_;
procedure PerformInitialAudit;
end;
implementation
uses
Tocsg.Safe, Tocsg.Strings, Tocsg.Path, Tocsg.Encrypt, superobject, Tocsg.Exception,
Winapi.Windows, GlobalDefine, AbUnzper, AbArcTyp, ManagerService,
ManagerModel, Condition, Tocsg.Packet;
{ TRecoverService }
Constructor TRecoverService.Create;
begin
Inherited Create(true, false);
bIsWorking_ := false;
bRecovering_ := false;
sBlkFRename_ := '';
sIgrBlkFRename_ := '';
bBlockRename_ := false;
KvBinFiles_ := TStringList.Create;
KvBinFiles_.CaseSensitive := false;
SplitString(KVBIN_FILES, '|', KvBinFiles_);
HeBinFiles_ := TStringList.Create;
HeBinFiles_.CaseSensitive := false;
SplitString(HEBIN_FILES, '|', HeBinFiles_);
ConfFiles_ := TStringList.Create;
ConfFiles_.CaseSensitive := false;
SplitString(CONF_FILES, '|', ConfFiles_);
ConfFiles_.Add(EXE_SPL);
LangFiles_ := TStringList.Create;
LangFiles_.CaseSensitive := false;
SplitString(LANG_FILES, '|', LangFiles_);
SLCoreFiles_ := TStringList.Create;
SLCoreFiles_.CaseSensitive := false;
SplitString(SLCORE_FILES, '|', SLCoreFiles_);
SLCoreDatas_ := TStringList.Create;
SplitString(SLCORE_DATA_FILES, '|', SLCoreDatas_);
DirNames_ := TStringList.Create;
DirNames_.CaseSensitive := false;
SplitString(DIR_NAMES, '|', DirNames_);
DataFiles_ := TStringList.Create;
DataFiles_.CaseSensitive := false;
SplitString(DATA_FILES, '|', DataFiles_);
LockFiles_ := TList<TFileStream>.Create;
LockFiles_.OnNotify := OnLockFileNotify;
LockFiles;
referenceData_ := TDictionary<string, string>.Create;
LoadReferenceJson(GetRunExePathDir + '' + 'Resource\rst.00');
// RecoverAll;
PerformInitialAudit;
SetFilter(FILE_NOTIFY_CHANGE_FILE_NAME or FILE_NOTIFY_CHANGE_DIR_NAME or
FILE_NOTIFY_CHANGE_SIZE or FILE_NOTIFY_CHANGE_LAST_WRITE);
end;
Destructor TRecoverService.Destroy;
begin
StopService;
Inherited;
FreeAndNil(LockFiles_);
FreeAndNil(DataFiles_);
FreeandNil(DirNames_);
FreeAndNil(SLCoreDatas_);
FreeAndNil(SLCoreFiles_);
FreeAndNil(LangFiles_);
FreeAndNil(ConfFiles_);
FreeAndNil(HeBinFiles_);
FreeAndNil(KvBinFiles_);
FreeAndNil(referenceData_);
end;
procedure TRecoverService.LoadReferenceJson(const JsonPath: string);
var
Path, Hash: string;
ss: TStringStream;
O, ItemObj: ISuperObject;
ListObj: TSuperArray;
i: Integer;
begin
referenceData_.Clear;
if not FileExists(JsonPath)
then Exit;
try
Guard(ss, TStringStream.Create('', TEncoding.UTF8));
ss.LoadFromFile(JsonPath);
// O := SO(ss.DataString);
O := SO(DecBinStrToStr(ekAes256cbc, PASS_MODEL, ss.DataString));
if O <> nil then
begin
ListObj := O.A['List'];
if ListObj <> nil then
begin
for i := 0 to ListObj.Length - 1 do
begin
ItemObj := ListObj.O[i];
// 비교를 위한 대소문자 정규화 (경로는 소문자, 해시는 대문자)
Path := LowerCase(ItemObj.S['P']);
Hash := UpperCase(ItemObj.S['H']);
// _Trace('[MGKIM] LoadReferenceJson.. P: %s, H: %s', [Path, Hash]);
referenceData_.AddOrSetValue(Path, Hash);
end;
end;
end;
except
on E: Exception do
ETgException.TraceException(Self, E, 'Fail .. LoadReferenceJson()');
end;
end;
procedure TRecoverService.OnLockFileNotify(Sender: TObject; const Item: TFileStream; Action: TCollectionNotification);
begin
if Action = cnRemoved then
Item.Free;
end;
procedure TRecoverService.LockFiles;
function DoLockFile(sPath: String): TFileStream;
begin
Result := nil;
if not FileExists(sPath) then
exit;
try
Result := TFileStream.Create(sPath, fmOpenRead or fmShareDenyWrite);
except
on E: Exception do
ETgException.TraceException(E, Format('Fail .. DoLockFile() .. Path="%s"', [sPath]));
end;
end;
var
sCurDir,
sResDir: String;
fs: TFileStream;
i: Integer;
begin
sCurDir := GetRunExePathDir;
sResDir := sCurDir + 'Resource\';
for i := 1 to 5 do
begin
fs := DoLockFile(sResDir + Format('rst.%.2d', [i]));
if fs <> nil then
LockFiles_.Add(fs);
end;
fs := DoLockFile(sCurDir + 'bin\datafiles\unicodetables\text_kjdump.txt');
if fs <> nil then
LockFiles_.Add(fs);
end;
procedure TRecoverService.UnlockFiles;
begin
LockFiles_.Clear;
end;
// 단일 파일 무결성 검사 (해시 비교)
function TRecoverService.CheckFileIntegrity(const FilePath, ExpectedHash: string; out ActualHash, Reason: string): Boolean;
begin
Result := False;
ActualHash := '';
Reason := '';
if not TFile.Exists(FilePath) then
begin
Reason := 'File Not Found';
Exit;
end;
try
ActualHash := UpperCase(THashSHA2.GetHashStringFromFile(FilePath, THashSHA2.TSHA2Version.SHA256));
if ActualHash = ExpectedHash then
Result := True
else
Reason := 'Hash Different';
except
on E: Exception do
Reason := 'Access Denied or Read Error';
end;
end;
function TRecoverService.DoRecoverFile(const sTargetFilePath: string): string;
var
zip: TAbUnZipper;
sCurDir, sResDir, sResPath, sExtrDir: String;
sFName, sFNameLower, sResFile: String;
nIdx: Integer;
begin
bRecovering_ := True;
try
try
sCurDir := GetRunExePathDir;
sResDir := sCurDir + 'Resource\';
sResPath := sCurDir + 'prfwork.dat';
sFName := ExtractFileName(sTargetFilePath);
sFNameLower := LowerCase(sFName);
sExtrDir := ExtractFilePath(sTargetFilePath);
// 손상된 파일 이름에 맞춰 원본 백업 리소스(rst.XX) 매핑
if sFNameLower = 'slcore.exe' then
sResFile := 'rst.05'
else if (sFNameLower = 'ssleay32.dll') or (sFNameLower = 'ptnsch.dat') or //conf
(sFNameLower = 'libkm64.dll') or (sFNameLower = 'libeay32.dll') or
(sFNameLower = 'kvcttschw.exe') or (sFNameLower = 'kvcttsch.exe') or
(sFNameLower = '7z.dll') or (sFNameLower = 'bs1flt_x64.sys') or
(sFNameLower = 'bs1fltctrl.dll') or (sFNameLower = 'bs1ugcp.dll') or
(sFNameLower = 'bsonex32.sys') or (sFNameLower = 'bsonex64.sys') or
(sFNameLower = 'ecrmhomeedition') or
(sFNameLower = 'ielib64.dll') or (sFNameLower = 'ecrmheserviced.dll') then
sResFile := 'rst.01'
else if (sFNameLower = 'ecrmintercaller.exe') or (sFNameLower = 'ecrmhehelper.dll') or // root
(sFNameLower = 'ecrmhehelper32.dll') or (sFNameLower = 'ecrmhehelperf.dll') or
(sFNameLower = 'ecrmhehelper32f.dll') or (sFNameLower = 'ecrmhehelper.exe') or
(sFNameLower = 'bswmcr.exe') or (sFNameLower = 'bs1out.dll') or
(sFNameLower = 'bs1tri.exe') or (sFNameLower = 'bs1shl.dll') or
(sFNameLower = 'Bs1ovi.dll') or (sFNameLower = 'Bs1ovm.dll') or
(sFNameLower = 'Bs1out.dll') or (sFNameLower = 'bs1out64.dll') then
sResFile := 'rst.03'
else if (Pos('ecrmhomeedition.4', sFNameLower) > 0) or (sFNameLower = 'eCrmHomeEdition.804.dat') then // 언어팩 dat 파일들
sResFile := 'rst.04'
else if Pos('\bin\', LowerCase(sExtrDir)) > 0 then // bin 폴더 하위 파일들
sResFile := 'rst.02'
else if sFNameLower = LowerCase(EXE_SPL) then // EXE_SPL 상수가 정의되어 있다면 주석 해제
sResFile := 'rst.06'
else
begin
Result:= 'Recover file fail, Resource file not define';
Exit;
end;
// 리소스 파일 존재 여부 확인
if not FileExists(sResDir + sResFile) then
begin
Result:= 'Recover file fail, Resource file not exist';
Exit;
end;
// 파일 복구 실행 (기존 CheckAndRecover + prfwork 로직)
try
// 원본 코드와 동일하게 prfwork.dat 에 파일 복사 시도
CopyFile(PChar(sResDir + sResFile), PChar(sResPath), False);
_Trace('[MGKIM] 파일 변경/삭제 복구 시도됨', 2);
_Trace('[MGKIM] DoRecover .. Path="%s" From="%s"', [sTargetFilePath, sResFile]);
// rst.06은 압축이 아닌 단일 파일이므로 바로 복사
if sResFile = 'rst.06' then
begin
CopyFile(PChar(sResDir + sResFile), PChar(sTargetFilePath), False);
end
else
begin
try
// 나머지는 Abbrevia를 통해 특정 파일(sFName)만 압축 해제
Guard(zip, TAbUnzipper.Create(nil));
zip.FileName := sResDir + sResFile; // 기존 CheckAndRecover처럼 원본 파일에서 직접 Read
nIdx := zip.FindFile(sFName);
if nIdx <> -1 then
begin
if ForceDirectories(sExtrDir) then
begin
zip.ExtractOptions := [eoCreateDirs, eoRestorePath];
zip.BaseDirectory := sExtrDir;
zip.ExtractFiles(sFName); // 손상된 단일 파일만 추출하여 덮어쓰기
_Trace('[MGKIM] 파일 변경/삭제 복구 성공', 2);
Result:= 'Recover file success';
end;
end
else
begin
Result:= 'Recover file fail, file not exist';
end;
except
on E: Exception do
begin
ETgException.TraceException(E, Format('[MGKIM] Fail .. CheckAndRecover(), sExtrDir=%s , Path="%s"', [sExtrDir, sFName]));
Result:= 'Recover file fail, exception : ' + E.ToString;
end;
end;
end;
finally
if FileExists(sResPath) then
DeleteFile(PChar(sResPath));
end;
except
on E: Exception do
ETgException.TraceException(E, Format('Fail .. DoRecoverFile(), Path="%s"', [sTargetFilePath]));
end;
finally
bRecovering_ := False;
Processor_.Clear;
end;
end;
procedure TRecoverService.PerformInitialAudit;
var
KeyPath, ExpectedHash, ActualHash, Reason: string;
Root, FileObj, SuccessArray, FailArray: ISuperObject;
JsonLog: string;
IsSuccess: Boolean;
begin
try
Root := SO();
SuccessArray := SA([]);
FailArray := SA([]);
for KeyPath in referenceData_.Keys do
begin
ExpectedHash := referenceData_[KeyPath];
IsSuccess := CheckFileIntegrity(KeyPath, ExpectedHash, ActualHash, Reason);
FileObj := SO();
FileObj.S['filePath'] := KeyPath;
if TFile.Exists(KeyPath) then
begin
FileObj.S['lastModifiedTime'] := FormatDateTime('yyyy-mm-dd hh:nn:ss.zzz', TFile.GetLastWriteTime(KeyPath));
FileObj.I['size'] := TFile.GetSize(KeyPath);
end
else
begin
FileObj.S['lastModifiedTime'] := '';
FileObj.I['size'] := 0;
end;
if IsSuccess then
begin
// 성공한 경우: reason 필드 없이 들어갑니다.
SuccessArray.AsArray.Add(FileObj);
end
else
begin
var RecoveResult: string;
RecoveResult:= DoRecoverFile(KeyPath);
FileObj.S['reason'] := Reason + ' RecoveResult: ' + RecoveResult; // "Hash Different", "Unknown File" 등
FailArray.AsArray.Add(FileObj);
end;
end;
Root.O['fail'] := FailArray;
Root.O['success'] := SuccessArray;
JsonLog := Root.AsJSon(True);
_Trace('[MGKIM] 생성된 JSON: %s', [JsonLog]);
gMgSvc.SendAuditLog(JsonLog);
except
on E: Exception do
ETgException.TraceException(Self, E, 'Fail .. SendAuditLog()');
end;
end;
procedure TRecoverService.CheckAndRecover(sResPath, sPath: String);
var
zip: TAbUnZipper;
nIdx: Integer;
sDir,
sFName: String;
begin
try
sFName := ExtractFileName(sPath);
Guard(zip, TAbUnzipper.Create(nil));
zip.FileName := sResPath;
nIdx := zip.FindFile(sFName);
if (nIdx <> -1) and (not FileExists(sPath) or (GetFileSize_path(sPath) <> zip.Items[nIdx].UncompressedSize)) then
begin
_Trace('파일 변경/삭제 감지됨', 2);
_Trace('DoRecover .. Path="%s"', [sPath]);
try
sDir := ExtractFilePath(sPath);
if ForceDirectories(sDir) then
begin
zip.ExtractOptions := [eoCreateDirs, eoRestorePath];
zip.BaseDirectory := sDir;
// zip.OnArchiveProgress := ;
// zip.OnNeedPassword := ;
// zip.ExtractAt(nIdx, sFName);
zip.ExtractFiles(sFName);
end;
except
on E: Exception do
ETgException.TraceException(E, Format('Fail .. CheckAndRecover(), Path="%s"', [sPath]));
end;
end;
except
on E: Exception do
ETgException.TraceException(E, 'Fail .. CheckAndRecover()');
end;
end;
procedure TRecoverService.RecoverAll;
procedure ExtrZip(sResPath, sDestDir: String; bIgrErr: Boolean = false);
var
zip: TAbUnZipper;
begin
if not ForceDirectories(sDestDir) then
exit;
try
Guard(zip, TAbUnzipper.Create(nil));
zip.FileName := sResPath;
zip.ExtractOptions := [eoCreateDirs, eoRestorePath];
zip.BaseDirectory := sDestDir;
// zip.OnArchiveProgress := ;
// zip.OnNeedPassword := ;
zip.ExtractFiles('*.*');
except
on E: Exception do
ETgException.TraceException(E, Format('Fail .. ExtrZip(), ExtrDir="%s"', [sDestDir]));
end;
end;
var
sResDir,
sCurDir,
sResPath,
sDestPath: String;
bDoRecover: Boolean;
i: Integer;
begin
bRecovering_ := true;
try
sCurDir := GetRunExePathDir;
sResDir := sCurDir + 'Resource\';
if not DirectoryExists(sResDir) then
exit;
bDoRecover := false;
sDestPath := sCurDir + 'bin\';
if DirectoryExists(sDestPath) then
begin
var dwDirCnt: DWORD := 0;
var dwFileCnt: DWORD := 0;
var llTotalSize: LONGLONG := 0;
GetDirInfo(sDestPath, dwDirCnt, dwFileCnt, llTotalSize, true);
if (dwDirCnt <> 2) or (dwFileCnt <> 260) or (llTotalSize <> 47648118) then
bDoRecover := true;
end else
bDoRecover := true;
if bDoRecover then
begin
_Trace('파일 변경/삭제 감지됨', 2);
_Trace('DoRecover .. Path="%s"', [sDestPath]);
ExtrZip(sResDir + 'rst.02', sDestPath);
bDoRecover := false;
end;
sResPath := sCurDir + 'prfwork.dat';
if FileExists(sResDir + 'rst.01') then
begin
// hebin
CopyFile(PChar(sResDir + 'rst.01'), PChar(sResPath), false);
sDestPath := sCurDir;
CheckAndRecover(sResDir + 'rst.01', sDestPath + 'ssleay32.dll');
CheckAndRecover(sResDir + 'rst.01', sDestPath + 'ptnsch.dat');
CheckAndRecover(sResDir + 'rst.01', sDestPath + 'libkm64.dll');
CheckAndRecover(sResDir + 'rst.01', sDestPath + 'libeay32.dll');
CheckAndRecover(sResDir + 'rst.01', sDestPath + 'KvCttSchw.exe');
CheckAndRecover(sResDir + 'rst.01', sDestPath + 'KvCttSch.exe');
CheckAndRecover(sResDir + 'rst.01', sDestPath + 'ielib64.dll');
CheckAndRecover(sResDir + 'rst.01', GetSystemDir + 'eCrmHeServiced.dll');
end;
if FileExists(sResDir + 'rst.03') then
begin
// conf
CopyFile(PChar(sResDir + 'rst.03'), PChar(sResPath), false);
sDestPath := sCurDir + 'conf\';
CheckAndRecover(sResDir + 'rst.03', sDestPath + 'eCrmInterCaller.exe');
CheckAndRecover(sResDir + 'rst.03', sDestPath + 'eCrmHeHelper.dll');
CheckAndRecover(sResDir + 'rst.03', sDestPath + 'eCrmHeHelper32.dll');
CheckAndRecover(sResDir + 'rst.03', sDestPath + 'eCrmHeHelperf.dll');
CheckAndRecover(sResDir + 'rst.03', sDestPath + 'eCrmHeHelper32f.dll');
CheckAndRecover(sResDir + 'rst.03', sDestPath + 'eCrmHeHelper.exe');
CheckAndRecover(sResDir + 'rst.03', sDestPath + 'BSWmcr.exe');
CheckAndRecover(sResDir + 'rst.03', sDestPath + 'Bs1out.dll');
CheckAndRecover(sResDir + 'rst.03', sDestPath + 'Bs1out64.dll');
end;
if FileExists(sResDir + 'rst.04') then
begin
CopyFile(PChar(sResDir + 'rst.04'), PChar(sResPath), false);
sDestPath := sCurDir + 'Language\';
CheckAndRecover(sResDir + 'rst.04', sDestPath + 'eCrmHomeEdition.412.dat');
CheckAndRecover(sResDir + 'rst.04', sDestPath + 'eCrmHomeEdition.409.dat');
end;
if FileExists(sResDir + 'rst.05') then
begin
CopyFile(PChar(sResDir + 'rst.05'), PChar(sResPath), false);
sDestPath := sCurDir;
CheckAndRecover(sResDir + 'rst.05', sDestPath + 'slcore.exe');
end;
if FileExists(sResDir + 'rst.06') and not FileExists(sCurDir + DIR_CONF + EXE_SPL) then
begin
CopyFile(PChar(sResDir + 'rst.06'), PChar(sCurDir + DIR_CONF + EXE_SPL), false);
_Trace('파일 변경/삭제 감지됨', 2);
_Trace('DoRecover .. Path="%s"', [sCurDir + DIR_CONF + EXE_SPL]);
end;
finally
if FileExists(sResPath) then
DeleteFile(PChar(sResPath));
bRecovering_ := false;
Processor_.Clear;
end;
end;
procedure TRecoverService.RecoverData;
var
sConfDir: String;
CompModel: TCompanyModel;
begin
try
sConfDir := GetRunExePathDir + 'conf\';
if ForceDirectories(sConfDir) then
begin
if not FileExists(sConfDir + DAT_COMPANY) then
begin
Guard(CompModel, TCompanyModel.Create);
CompModel.CustomerType := CUSTOMER_TYPE;
CompModel.CustomerSubType := CUSTOMER_SUB_TYPE;
CompModel.SvrDestList.AddStrings(gMgSvc.ServerUrlList);
CompModel.Save(sConfDir + DAT_COMPANY);
end;
if not FileExists(sConfDir + DAT_AGENT) then
begin
_Trace('DoRecoverData .. File="%s"', [DAT_AGENT]);
gMgSvc.AgentModel.Save;
end;
if gMgSvc.IsNewApi then
begin
// todo : 정책 데이터 복구 추가 23_0810 08:40:35 kku
if gMgSvc.PrefModel.Loaded then
gMgSvc.PrefModel.Save;
if gMgSvc.SleepPolicy.Loaded then
gMgSvc.SleepPolicy.Save;
if gMgSvc.VulPolicy.Loaded then
gMgSvc.VulPolicy.Save;
if gMgSvc.OffPolicy.Loaded then
gMgSvc.OffPolicy.Save;
if gMgSvc.ExpPolicy.Loaded then
gMgSvc.ExpPolicy.Save;
end
else
begin
if not FileExists(sConfDir + DAT_PREF) then
begin
_Trace('DoRecoverData .. File="%s"', [DAT_PREF]);
gMgSvc.PrefModel.Save;
end;
if not FileExists(sConfDir + DAT_CTTSCH) then
begin
_Trace('DoRecoverData .. File="%s"', [DAT_CTTSCH]);
gMgSvc.MgCttSch.Save;
end;
end;
end;
except
on E: Exception do
ETgException.TraceException(Self, E, 'Fail .. RecoverData()');
end;
end;
procedure TRecoverService.StartService;
var
dwLogicalDrv: DWORD;
i: Integer;
sDrive: String;
begin
if not bIsWorking_ then
begin
AddDirWatch(GetRunExePathDir);
// AddDirWatch(GetProgramFilesDir + DIR_HE);
bIsWorking_ := true;
Processor_.StartThread;
end;
end;
procedure TRecoverService.StopService;
begin
if bIsWorking_ then
begin
bIsWorking_ := false;
Processor_.Clear;
Processor_.PauseThread;
try
ClearDirWatch;
except
on E: Exception do
ETgException.TraceException(Self, E, 'Fail .. StopService()');
end;
end;
end;
procedure TRecoverService.ProcessDirWatchEnt(Sender: TObject; pInfo: PDirWatchEnt);
procedure RecoverFile(sPath: String);
var
sCurDir,
sResName: String;
zip: TAbUnZipper;
begin
try
sCurDir := GetRunExePathDir;
sPath := StringReplace(sPath, sCurDir, '', [rfReplaceAll, rfIgnoreCase]);
sResName := GetRunExePathDir + 'Resource\' + sResName;
if not FileExists(sResName) then
exit;
Guard(zip, TAbUnZipper.Create(nil));
zip.FileName := sResName;
zip.ExtractOptions := [eoCreateDirs, eoRestorePath];
// zip.BaseDirectory := sDestDir;
except
on E: Exception do
ETgException.TraceException(Self, E, 'Fail .. RecoverFile()');
end;
end;
var
sExt,
sDir,
sFName,
sIgCheck,
sDestPath: String;
i: Integer;
begin
try
if bRecovering_ then
exit;
sDir := ExtractFilePath(pInfo.sPath);
sFName := ExtractFileName(pInfo.sPath);
sExt := GetFileExt(sFName);
case pInfo.dwAction of
1 : ; // Add
2 : ;// Delete
3 : ;
4 : ;
5 :
begin
if (KvBinFiles_.IndexOf(sFName) <> -1) or
(HeBinFiles_.IndexOf(sFName) <> -1) or
(ConfFiles_.IndexOf(sFName) <> -1) or
(LangFiles_.IndexOf(sFName) <> -1) or
(SLCoreFiles_.IndexOf(sFName) <> -1) or
(DirNames_.IndexOf(sFName) <> -1) then
begin
// ExpectedHash := referenceData_[KeyPath];
// RecoverAll;
PerformInitialAudit;
end;
if DataFiles_.IndexOf(sFName) <> -1 then
RecoverData;
// if (gClient <> nil) and gClient.Connected then
// begin
// for i := 0 to SLCoreDatas_.Count - 1 do
// begin
// if Pos(SLCoreDatas_[i], sFName) = 1 then
// begin
// gClient.SendPacket(TTgPacket.Create(SLC_REQUEST_SAVEDATA));
// break;
// end;
// end;
// end;
end;
// 3 : // Modify
// begin
// if (KvBinFiles_.IndexOf(sFName) <> -1) or
// (HeBinFiles_.IndexOf(sFName) <> -1) or
// (ConfFiles_.IndexOf(sFName) <> -1) or
// (LangFiles_.IndexOf(sFName) <> -1) or
// (SLCoreFiles_.IndexOf(sFName) <> -1) or
// (DirNames_.IndexOf(sFName) <> -1) then
// begin
//// RecoverAll;
// PerformInitialAudit;
// end;
// end;
// 4 : // Rename
// begin
// if sIgrBlkFRename_ = sFName then
// begin
// sIgrBlkFRename_ := '';
// exit;
// end;
//
// if (KvBinFiles_.IndexOf(sFName) <> -1) or
// (HeBinFiles_.IndexOf(sFName) <> -1) or
// (ConfFiles_.IndexOf(sFName) <> -1) or
// (LangFiles_.IndexOf(sFName) <> -1) or
// (SLCoreFiles_.IndexOf(sFName) <> -1) or
// (DirNames_.IndexOf(sFName) <> -1) then
// begin
// sBlkFRename_ := sFName;
// bBlockRename_ := true;
// end;
// end;
// 5 :
// begin
// // 이름 변경 복구 체크
// if sBlkFRename_ <> '' then
// begin
// if bBlockRename_ then
// begin
// sIgrBlkFRename_ := sFName;
// bBlockRename_ := false;
// if MoveFile_wait(pInfo.sPath, sDir + sBlkFRename_, 5) then
// begin
// sFName := sBlkFRename_;
// pInfo.sPath := sDir + sFName;
// end;
// end;
//
// sBlkFRename_ := '';
// end;
// end;
// else exit;
end;
except
on E: Exception do
ETgException.TraceException(Self, E, 'Fail .. ProcessDirWatchEntry()')
end;
end;
end.