{*******************************************************} { } { 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; bIsWorking_: Boolean; bBlockRename_: Boolean; sBlkFRename_, sIgrBlkFRename_: String; bRecovering_: Boolean; referenceData_: TDictionary; 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.Create; LockFiles_.OnNotify := OnLockFileNotify; LockFiles; referenceData_ := TDictionary.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.