{*******************************************************} { } { ProcessUninstall } { } { Copyright (C) 2022 kku } { } {*******************************************************} unit ProcessUninstall; interface uses System.SysUtils, Winapi.Windows, System.Classes; function UninstallXPrt(bIgrDelCfg: Boolean): Boolean; function UninstallCrmHE(dwExitIgrPid: DWORD = 0; bIgrDelCfg: Boolean = false): Boolean; implementation uses {$IFDEF _HE_} ManagerService, {$ENDIF} Tocsg.Path, Tocsg.Process, Tocsg.Service, Tocsg.Files, GlobalDefine, Tocsg.Win32, Tocsg.Safe, Tocsg.Firewall, Winapi.ActiveX, Tocsg.Shell, Tocsg.Registry, superobject, DefineHelper, Tocsg.Trace, GlobalOutAddInDefine, Tocsg.Exception, Tocsg.Disk, Tocsg.Driver, Condition, madCodeHook; var arrForceDelConfFiles: array [0..20] of String = (EXE_MG, EXE_GC, EXE_RT, EXE_IC, DLL_HOOK, DLL_HOOK32, EXE_HP, EXE_LB, DLL_SHELL, EXE_OCR, DAT_CTTSCHRSTDATA_EXP, DLL_OT, DLL_OT64, EXE_KF{KFTC}, DLL_OVI_DRM, DLL_OVI_AIP, DLL_ST64, DLL_FAS64, DAT_FILEEXP, DLL_PDFIUM, EXE_BROWSER_SECU); arrXprintFiles: array [0..9] of String = ('BSonehlink.dll', 'BSonehlink64.dll', 'BSoneprint.dll', 'BSoneprint64.dll', 'BSoneprintclient.exe', 'BSoneprintclient64.exe', 'BSonex32.sys', 'BSonex64.sys', 'Newtonsoft.Json.dll', 'xPrintTest.exe'); function HasRes(sId: String): Boolean; var res: TResourceStream; begin Result := false; try res := TResourceStream.Create(HInstance, sId, 'raw'); if res <> nil then begin Result := true; res.Free; end; except on E: Exception do ETgException.TraceException(E, Format('Fail .. HasRes(), ID="%s"', [sId])); end; end; function UninstallXPrt(bIgrDelCfg: Boolean): Boolean; var xPrtDir, sFName, sTemp: String; i, nTO: Integer; IgrList: TStringList; begin Result := false; try xPrtDir := 'C:\ProgramData\bsoneprint\'; if FileExists(xPrtDir + EXE_xPrintSvc) then begin if not bIgrDelCfg then begin TerminateProcessByName(EXE_xPrintUI); Sleep(500); end else begin if GetProcessPidByName(EXE_xPrintUI) > 0 then begin TTgTrace.T('Fail .. UninstallXPrt() .. xPrint UI 실행 중', 1); exit; end; end; // ServiceStop('BSonePrintService'); // UninstallService('BSonePrintService'); ExecuteAppWaitUntilTerminate(xPrtDir + EXE_xPrintSvc, '-uninstall', SW_HIDE, 10000); nTO := 0; // 서비스 프로세스가 종료될때까지 최대 15초간 기다려준다 25_0826 18:00:56 kku while (GetProcessPidByName('BSoneprintclient.exe') <> 0) or (GetProcessPidByName(EXE_xPrintSvc) <> 0) do begin Inc(nTO); Sleep(500); if nTO >= 30 then break; end; for i := Low(arrXprintFiles) to High(arrXprintFiles) do begin sFName := arrXprintFiles[i]; if FileExists(xPrtDir + sFName) and not DeleteFile(PChar(xPrtDir + sFName)) then begin sTemp := '$d-' + sFName + '-' + FormatDateTime('yymmddhhnnss', Now); MoveFile_wait(xPrtDir + sFName, xPrtDir + sTemp, 2); DeleteFile(PChar(xPrtDir + sTemp)); end; end; Guard(IgrList, TStringList.Create); if bIgrDelCfg then begin IgrList.Add('Data\'); IgrList.Add('logs\'); IgrList.Add('partbill.ini'); IgrList.Add('bsoneprofile.conf'); end; DeleteDir(xPrtDir, true, true, IgrList); Result := true; end; except on E: Exception do ETgException.TraceException(E, 'Fail .. UninstallXPrt()'); end; end; procedure ReleaseDriveSecu; var i: Integer; dwLogicalDrv: DWORD; sDrive: String; DriveInfo: TDriveInfo; begin try dwLogicalDrv := GetLogicalDrives; for i := 0 to 31 do if (dwLogicalDrv and (1 shl i)) > 0 then begin sDrive := Format('%s:\', [Char(Integer('A')+i)]); if not DirectoryExists(sDrive) then continue; if UpCase(sDrive[1]) = 'C' then continue; if IsReadOnlyByWriteProbe(sDrive) = 1 then begin GetDriveDetail(sDrive, @DriveInfo); SetDriveReadOnly(sDrive, DriveInfo.nDiskNum, false); end; end; except on E: Exception do ETgException.TraceException(E, 'Fail .. ReleaseDriveSecu()'); end; end; function UninstallCrmHE(dwExitIgrPid: DWORD = 0; bIgrDelCfg: Boolean = false): Boolean; var sTemp, sFName, sSysDir, sInstDir, sDataDir: String; nTO: Integer; KillMtx, UnInstMtx: TTgMutex; IgrList: TStringList; i: Integer; bDoRemove, bRestartExplorer: Boolean; state: Boolean; begin Result := false; bRestartExplorer := false; if not bIgrDelCfg then UnInstMtx := TTgMutex.Create(MUTEX_UNINSTALL) else UnInstMtx := nil; Guard(KillMtx, TTgMutex.Create(MUTEX_KILL)); try nTO := 0; // 먼저... 알아서 죽도록 기다림 while MutexExists(MUTEX_AGENT) or MutexExists(MUTEX_SERVICE) do begin Inc(nTO); Sleep(500); OutputDebugString(Pchar(Format('[MGKIM] UninstallCrmHE .. MUTEX_AGENT wait (%d)',[nTO]))); if nTO >= 20 then break; end; finally if UnInstMtx <> nil then FreeAndNil(UnInstMtx); end; Sleep(1000); {$IFNDEF _SILENT_} {$IF not Defined(_SHSC_) or not Defined(_SHCI_)} // 신한신용정보, 신한투자증권은 보안프로그램에 쓰기테스트 파일이 감지된다 25_1030 19:45:39 kku case CUSTOMER_TYPE of CUSTOMER_SHSC, CUSTOMER_SHCI : ; else ReleaseDriveSecu; end; {$IFEND} {$ENDIF} // _SILENT_ sInstDir := GetProgramFilesDir + DIR_HE; if not DirectoryExists(sInstDir) then begin Result := true; exit; end; if DirectoryExists(sInstDir + 'Language\') then DeleteDir(sInstDir + 'Language\'); OutputDebugString(Pchar('[MGKIM] UninstallCrmHE .. fltmc bslflt')); ExecutePath_hide('fltmc.exe', 'unload bs1flt'); TerminateProcessByName(EXE_SV); TerminateProcessByName(EXE_SL); state := TerminateProcessByName(EXE_HE, dwExitIgrPid); if not state then OutputDebugString(Pchar(Format('[MGKIM] UninstallCrmHE .. EXE_HE(%s) Kill Fail : %d', [EXE_HE, GetLastError]))); TerminateProcessByName('javaw.exe'); TerminateProcessByName(EXE_MG); TerminateProcessByName(EXE_RT); TerminateProcessByName(EXE_GC); TerminateProcessByName(EXE_IC); TerminateProcessByName(EXE_KF); TerminateProcessByName(EXE_CS); TerminateProcessByName(EXE_CW); TerminateProcessByName(EXE_KV); TerminateProcessByName(EXE_AIP); TerminateProcessByName(EXE_BROWSER_SECU); TerminateProcessByName('xPrintTest.exe'); TerminateProcessByName('BSOne-AIP-Decrypt-OP.exe'); Sleep(500); TerminateProcessByName(EXE_KV); // 바로 재실행되서 한번 더 시도해준다 bDoRemove := not bIgrDelCfg; StopInjectionDriver(BS1HOOK_DRIVERTAG); // 아웃룩 플러그인(Bs1out.dll, Bs1out64.dll) 업데이트가 있을때만 활성화 시켜준다 25_0924 14:08:42 kku // if ExistsKey(HKEY_CLASSES_ROOT, REG_BS1OutlookAddInKey) then // TerminateProcessByName('outlook.exe'); sSysDir := GetSystemDir; // 이거 살림. SetVisibleService(false) 사용하던 구버전 업데이트 시 필요 25_0423 12:39:56 kku SetVisibleService(NAME_SERVICE, true); Sleep(1000); if bDoRemove then begin if ExistsKey(HKEY_CLASSES_ROOT, REG_BS1OutlookAddInKey) then begin TerminateProcessByName('outlook.exe'); Sleep(500); ExecutePath_hide('regsvr32.exe', Format('/u /s "%s"', [sInstDir + DIR_CONF + DLL_ADDIN])); ExecutePath_hide('regsvr32.exe', Format('/u /s "%s"', [sInstDir + DIR_CONF + DLL_ADDIN64])); end; if FileExists(sInstDir + DIR_CONF + DLL_OT) then ExecutePath_hide('regsvr32.exe', Format('/u /s "%s"', [sInstDir + DIR_CONF + DLL_OT])); if FileExists(sInstDir + DIR_CONF + DLL_OT64) then ExecutePath_hide('regsvr32.exe', Format('/u /s "%s"', [sInstDir + DIR_CONF + DLL_OT64])); sTemp := sInstDir + DIR_CONF + DLL_OVI_DRM; if ExistsKey(HKEY_LOCAL_MACHINE, REG_BS1_OVI_DRM) and FileExists(sTemp) then begin ExecutePath_hide('regsvr32.exe', Format('/u /s "%s"', [sTemp])); bRestartExplorer := true; end; sTemp := sInstDir + DIR_CONF + DLL_OVI_AIP; if ExistsKey(HKEY_LOCAL_MACHINE, REG_BS1_OVI_AIP) and FileExists(sTemp) then begin ExecutePath_hide('regsvr32.exe', Format('/u /s "%s"', [sTemp])); bRestartExplorer := true; end; // 파수 DLL 해제 sTemp := sInstDir + DIR_CONF + DLL_FAS64; // 컴퓨터\HKEY_LOCAL_MACHINE\SOFTWARE\WOW6432Node\Classes\TypeLib\{D3135A34-059E-4A47-AAD4-0D84F41DC165} if ExistsKey(HKEY_CLASSES_ROOT, 'TypeLib\{D3135A34-059E-4A47-AAD4-0D84F41DC165}\1.0\0\win64') and FileExists(sTemp) then begin ExecutePath_hide('regsvr32.exe', Format('/u /s "%s"', [sTemp])); bRestartExplorer := true; end; end; if ServiceExists(NAME_SERVICE) then begin if FileExists(sSysDir + DLL_SV) then UninstallServiceDll(sSysDir + DLL_SV) else UninstallService(NAME_SERVICE); DelRegKey(HKEY_LOCAL_MACHINE, 'SYSTEM\CurrentControlSet\Control\SafeBoot\Minimal\SvcCrmHe'); DelRegKey(HKEY_LOCAL_MACHINE, 'SYSTEM\CurrentControlSet\Control\SafeBoot\Network\SvcCrmHe'); end; if ServiceExists(NAME_SERVICE_OLD) then UninstallService(NAME_SERVICE_OLD); Sleep(500); DeleteFile(PChar(sSysDir + EXE_SV)); DeleteFile(PChar(sSysDir + DLL_SV)); DeleteFile(PChar(sSysDir + EXE_SL)); DeleteFile(PChar(sSysDir + BAT_HE)); DeleteFile(PChar(sInstDir + 'conf\d_' + EXE_MG)); DeleteFile_wait(sInstDir + DAT_AIPUP); if bDoRemove then begin // 화면보호기 되돌림 23_0612 15:30:46 kku var sUserSid: String := GetRegRecentUserSid; if sUserSid <> '' then begin sTemp := GetRegValueAsString(HKEY_USERS, sUserSid + '\Control Panel\Desktop', 'toBkSCRNSAVE.EXE'); if sTemp <> '' then begin SetRegValueString(HKEY_USERS, sUserSid + '\Control Panel\Desktop', 'SCRNSAVE.EXE', sTemp, true); DelRegValue(HKEY_USERS, sUserSid + '\Control Panel\Desktop', 'toBkSCRNSAVE.EXE'); end; end; // 에어로 피크 해제 설정 제거 25_0924 13:31:03 kku sTemp := sUserSid + '\Software\Microsoft\Windows\CurrentVersion\Explorer\Advanced'; DelRegValue(HKEY_USERS, sTemp, 'DisablePreviewDesktop'); DelRegValue(HKEY_USERS, sTemp, 'DisablePreviewWindow'); // 크롬, 엣지 설정 되돌리기 23_1227 11:29:54 kku if GetRegValueAsInteger(HKEY_LOCAL_MACHINE, 'SOFTWARE\Policies\Microsoft\Edge', 'BS1') = 9 then DelRegKey(HKEY_LOCAL_MACHINE, 'SOFTWARE\Policies\Microsoft\Edge'); if GetRegValueAsInteger(HKEY_LOCAL_MACHINE, 'SOFTWARE\Policies\Google\Chrome', 'BS1') = 9 then DelRegKey(HKEY_LOCAL_MACHINE, 'SOFTWARE\Policies\Google\Chrome'); // 위치 서비스 강제 활성 복원 25_0827 14:27:30 kku if GetRegValueAsInteger(HKEY_LOCAL_MACHINE, 'SOFTWARE\Policies\Microsoft\Windows\AppPrivacy', 'BsLaal') = 1 then begin DelRegValue(HKEY_LOCAL_MACHINE, 'SOFTWARE\Policies\Microsoft\Windows\AppPrivacy', 'LetAppsAccessLocation'); DelRegValue(HKEY_LOCAL_MACHINE, 'SOFTWARE\Policies\Microsoft\Windows\AppPrivacy', 'BsLaal'); end; // 완전히 삭제 전 처리 // 쉘 DLL 정리 sTemp := sInstDir + DIR_CONF + DLL_SHELL; if ExistsKey(HKEY_CLASSES_ROOT, REG_BS1_SHELL) and FileExists(sTemp) then begin ExecutePath_hide('regsvr32.exe', '/s /u "' + sTemp + '"'); Sleep(500); DeleteFile(PChar(sTemp)); // if not DeleteFile(PChar(sInstDir + DIR_CONF + DLL_SHELL)) then if FileExists(sTemp) then bRestartExplorer := true; end; end; if bRestartExplorer then begin TerminateProcessByName('explorer.exe'); Sleep(500); ExecuteAppAsUser('msedge.exe', 'explorer.exe', '', SW_HIDE); end; if not bIgrDelCfg or HasRes('RS_XPRINT_DATA') then UninstallXPrt(bIgrDelCfg); for i := Low(arrForceDelConfFiles) to High(arrForceDelConfFiles) do begin sFName := arrForceDelConfFiles[i]; if FileExists(sInstDir + DIR_CONF + sFName) and not DeleteFile(PChar(sInstDir + DIR_CONF + sFName)) then begin sTemp := '$d-' + sFName + '-' + FormatDateTime('yymmddhhnnss', Now); MoveFile_wait(sInstDir + DIR_CONF + sFName, sInstDir + DIR_CONF + sTemp, 2); if sFName = DLL_HOOK then begin // EjectModuleFromPath2(sInstDir + DIR_CONF + DLL_HOOK, 'olk.exe|ms-teams.exe|msedgewebview2.exe'); // Sleep(500); // EjectModuleFromPath2(sInstDir + DIR_CONF + DLL_HOOK, 'olk.exe|ms-teams.exe|msedgewebview2.exe'); end else if sFName = DLL_HOOK32 then begin // ExecutePath_hide(sInstDir + DIR_CONF + EXE_HP, '-clearhook'); Sleep(500); end else begin TerminateProcessByName(sFName); end; DeleteFile(PChar(sInstDir + sTemp)); // 다시 삭제 시도하고 안되면 나중에 정리로 맡김 22_0922 09:16:48 kku end; end; sDataDir := sInstDir[1] + ':\ProgramData\Tocsg\bs1\'; if DirectoryExists(sDataDir) then begin DeleteFile(PChar(sDataDir + 'CI.bmp')); var arrData: array [0..1] of String; arrData[0] := DLL_HOOK; arrData[1] := DLL_HOOK32; for i := Low(arrData) to High(arrData) do begin sFName := arrData[i]; if FileExists(sDataDir + sFName) and not DeleteFile(PChar(sDataDir + sFName)) then begin sTemp := '$d-' + sFName + '-' + FormatDateTime('yymmddhhnnss', Now); MoveFile_wait(sDataDir + sFName, sDataDir + sTemp, 2); end; end; end; IgrList := nil; if bIgrDelCfg then begin IgrList := TStringList.Create; IgrList.Add(DIR_CONF); IgrList.Add(DIR_CACHE); IgrList.Add(DIR_KV); // IgrList.Add(DIR_AIP12); IgrList.Add(DIR_AIP14); IgrList.Add(DIR_AIP17); IgrList.Add(DAT_PREF); IgrList.Add(DAT_AGENT); IgrList.Add(DAT_COMPANY); IgrList.Add(DAT_CTTSCH); IgrList.Add(DAT_CLTFLD); IgrList.Add(DAT_RULE); IgrList.Add(DAT_PRTWTEXCEPT); IgrList.Add('prevfeature.ini'); IgrList.Add('browpolicy.ini'); IgrList.Add(NAME_PREF + '-01' + EXT_PROP); IgrList.Add(NAME_PREF + '-02' + EXT_PROP); IgrList.Add(NAME_PREF + '-03' + EXT_PROP); IgrList.Add(NAME_PREF + '-04' + EXT_PROP); IgrList.Add(NAME_PREF + '-05' + EXT_PROP); IgrList.Add(DAT_CAMPEXCEPT); IgrList.Add(DAT_FIXDISK); IgrList.Add(DAT_CAMPN); IgrList.Add(PROP_USERINFO); IgrList.Add(INI_HE); IgrList.Add('Log'); IgrList.Add('Data'); IgrList.Add('Resource'); IgrList.Add('sltgd.dat'); IgrList.Add(EXE_SPL); IgrList.Add('spl2pdf_lib'); IgrList.Add('AIP'); IgrList.Add(ExcludeTrailingPathDelimiter(DIR_CTTSCHRST)); IgrList.Add(EXE_SafePCUninst); DeleteDir('C:\ProgramData\HE\'); // 마지막 정책 수신값 정리, 업데이트 이후 정책 새로 업데이트를 위함 23_0907 10:27:09 kku DelRegValue(HKEY_LOCAL_MACHINE, REG_HE, 'LP'); end else begin // 완전히 삭제 후 처리 // 방화벽 설정 정리 22_0519 09:41:28 kku CoInitialize(nil); try ClearCrmFwPolicy(nil, true); finally CoUninitialize; end; // 레지스트리 정리 DelRegKey(HKEY_LOCAL_MACHINE, REG_HE); end; try // nTO := 0; // while (nTO < 20) and not Result do // begin // DeleteDir(sInstDir, true, true, IgrList); // Sleep(500); // Inc(nTO); // Result := not DirectoryExists(sInstDir); // // // 음.. 패치는 전체 다 삭제 안되는게 정상이니까 일단 이렇게 처리... // if (IgrList <> nil) and (nTO > 2) then // break; // end; // 훅 DLL 삭제가 안될 수 있기 때문에 이젠 파일이 남아있어도 정상처리 해줌 22_0922 10:13:44 kku DeleteDir(sInstDir, true, true, IgrList); Result := true; finally if IgrList <> nil then FreeAndNil(IgrList); end; end; end.