BSOne.SFC/eCrmHE/EXE_eCrmHeInstaller/ProcessUninstall.pas

495 lines
16 KiB
Plaintext

{*******************************************************}
{ }
{ 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;
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);
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\');
TerminateProcessByName(EXE_SV);
TerminateProcessByName(EXE_SL);
TerminateProcessByName(EXE_HE, dwExitIgrPid);
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.