{*******************************************************} { } { ThdMtpMon } { } { Copyright (C) 2022 kku } { } {*******************************************************} unit ThdMtpMon; interface uses Tocsg.Thread, System.SysUtils, System.Classes, Winapi.Windows, Tocsg.MTP, Winapi.Messages, System.Generics.Collections, ManagerModel; const WM_MTP_NOTIFY = WM_USER + 8523; type TPreventMtp = record bPrevent: Boolean; sIgrDevId: String; end; PBlockMtp = ^TBlockMtp; TBlockMtp = record sDevId: String; nTryCnt: Integer; end; TBlockMtpList = TList; TThdMtpMon = class(TTgThread) protected hRcvWnd_: HWND; PreventMtp_: TPreventMtp; MgMtp_: TManagerMtpDev; BlockMtpList_: TBlockMtpList; procedure OnBlockMtpNotify(Sender: TObject; const Item: PBlockMtp; Action: TCollectionNotification); procedure Execute; override; public Constructor Create; overload; Constructor Create(hRcvWnd: HWND; aPreventMtp: TPreventMtp); overload; Destructor Destroy; override; end; implementation uses {$IFDEF _HE_} ManagerService, GlobalDefine, {$ENDIF} Tocsg.Exception, Tocsg.Driver, Tocsg.Safe, Tocsg.Strings, Condition; { TThdMtpMon } Constructor TThdMtpMon.Create; begin Inherited Create; hRcvWnd_ := 0; BlockMtpList_ := TBlockMtpList.Create; BlockMtpList_.OnNotify := OnBlockMtpNotify; ZeroMemory(@PreventMtp_, SizeOf(PreventMtp_)); MgMtp_ := TManagerMtpDev.Create; // MgMtp_.RefreshMptDev; end; Constructor TThdMtpMon.Create(hRcvWnd: HWND; aPreventMtp: TPreventMtp); begin Create; hRcvWnd_ := hRcvWnd; PreventMtp_ := aPreventMtp; end; Destructor TThdMtpMon.Destroy; begin Inherited; if MgMtp_ <> nil then FreeAndNil(MgMtp_); FreeAndNil(BlockMtpList_); end; procedure TThdMtpMon.OnBlockMtpNotify(Sender: TObject; const Item: PBlockMtp; Action: TCollectionNotification); begin if Action = cnRemoved then Dispose(Item); end; procedure TThdMtpMon.Execute; var ChkMgMtp: TManagerMtpDev; bPrevent: Boolean; IgrDevList, IgrDevVdList: TStringList; sChkName: String; bIgrVender: Boolean; pBlockEnt: PBlockMtp; pEnt: PMtpEnt; {$IFDEF _HE_} sMsg, sData, sExcept, sExceptVender: String; MtpBlockKind: TUsbBlockKind; {$ENDIF} procedure ProcessMtpDev(aMtpBlockKind: TUsbBlockKind; var aMtpDevs: TManagerMtpDev); var i, c: Integer; begin try for i := aMtpDevs.MtpEntList.Count - 1 downto 0 do begin // if aMtpDevs.MtpEntList[i].sName = '' then // begin // // 이름이 비어 있는 경우 차단은 가능하지만 정확한 장치 이름을 남길수가 없기때문에 // // 이름이 채워질때까지 차단하지 않는다 25_0923 09:50:58 kku // aMtpDevs.MtpEntList.Delete(i); // continue; // end; if MgMtp_.GetMtpEntByDevId(aMtpDevs.MtpEntList[i].sDevId) = nil then begin bPrevent := false; {$IFDEF _HE_} if aMtpBlockKind = ubkBlock then {$ELSE} if PreventMtp_.bPrevent then {$ENDIF} begin if IgrDevList.IndexOf(aMtpDevs.MtpEntList[i].sDevId) = -1 then begin sChkName := UpperCase(aMtpDevs.MtpEntList[i].sName + '|' + aMtpDevs.MtpEntList[i].sDesc + '|' + aMtpDevs.MtpEntList[i].sDevId); bIgrVender := false; for c := 0 to IgrDevVdList.Count - 1 do begin if Pos(IgrDevVdList[c], sChkName) > 0 then begin bIgrVender := true; break; end; end; if not bIgrVender then begin bPrevent := RemoveUsbDevEnableByDevPath(aMtpDevs.MtpEntList[i].sDevId) < 2; if not bPrevent then begin _Trace('Fail .. BlockMTP, Reg, DevId="%s"', [aMtpDevs.MtpEntList[i].sDevId]); New(pBlockEnt); pBlockEnt.sDevId := aMtpDevs.MtpEntList[i].sDevId; pBlockEnt.nTryCnt := 0; BlockMtpList_.Add(pBlockEnt); continue; end; end; end; end; {$IFDEF _HE_} with aMtpDevs.MtpEntList[i]^ do begin sMsg := Format('Name : %s, Desc : %s, Serial : %s', [sName, sDesc, sDevId]); sData := sName + '|' + sDesc + '|' + sDevId; if bPrevent then begin sData := sData + '|PV'; if gMgSvc.IsNewApi then begin var LogInfo: TLogInfo; ZeroMemory(@LogInfo, SizeOf(LogInfo)); LogInfo.sCode := LOGCODE_PREVENT_MTP; LogInfo.sSummary := sMsg; LogInfo.sDevName := sName; LogInfo.sDevSerial := sDevId; LogInfo.sDevClassId := sDesc; gMgSvc.SendEventLogEx(@LogInfo); end else gMgSvc.SendEventLog(URI_USER_ACTION, LOGCODE_PREVENT_MTP, sMsg); if gMgSvc.ModePolicy.MTPPopup then gMgSvc.PopupMessage(TYPE_MSG_PREVENT_MTP, sData); end else begin case MtpBlockKind of ubkBlock : sMsg := 'Excepted, ' + sMsg; ubkLog, ubkReadOnly : begin if IsDivPopup then begin if gMgSvc.ModePolicy.MtpAllowPopup then begin if IgrDevList.IndexOf(sDevId) = -1 then gMgSvc.PopupMessage(TYPE_MSG_PREVENT_MTP, sData); end; end else begin if gMgSvc.ModePolicy.MTPPopup then begin if IgrDevList.IndexOf(sDevId) = -1 then gMgSvc.PopupMessage(TYPE_MSG_PREVENT_MTP, sData); end; end; end; end; if gMgSvc.IsNewApi then begin var LogInfo: TLogInfo; ZeroMemory(@LogInfo, SizeOf(LogInfo)); LogInfo.sCode := LOGCODE_EVENT_MTP; LogInfo.sSummary := sMsg; LogInfo.sDevName := sName; LogInfo.sDevSerial := sDevId; LogInfo.sDevClassId := sDesc; gMgSvc.SendEventLogEx(@LogInfo, false); end else gMgSvc.SendEventLog(URI_USER_ACTION, LOGCODE_EVENT_MTP, sMsg, false); end; end; {$ELSE} if hRcvWnd_ <> 0 then SendMessage(hRcvWnd_, WM_MTP_NOTIFY, Integer(bPrevent), NativeUInt(aMtpDevs.MtpEntList[i])); {$ENDIF} if bPrevent then aMtpDevs.MtpEntList.Delete(i); end; end; except on E: Exception do ETgException.TraceException(Self, E, 'Fail .. ProcessMtpDev()'); end; end; var i: Integer; begin ChkMgMtp := nil; Guard(IgrDevList, TStringList.Create); IgrDevList.CaseSensitive := false; Guard(IgrDevVdList, TStringList.Create); // 이미지 연결되어 있는 MTP 장치 차단을 위해 추가 23_1226 14:49:15 kku ChkMgMtp := TManagerMtpDev.Create; ChkMgMtp.RefreshMptDev; ProcessMtpDev(gMgSvc.ModePolicy.MtpBlockKind, ChkMgMtp); FreeAndNil(ChkMgMtp); MgMtp_.RefreshMptDev; {$IFDEF _HE_} sExcept := ''; sExceptVender := ''; {$ELSE} SplitString(PreventMtp_.sIgrDevId, ';', IgrDevList); {$ENDIF} try while not Terminated and not GetWorkStop do begin try if ChkMgMtp = nil then begin ChkMgMtp := TManagerMtpDev.Create; ChkMgMtp.RefreshMptDev; end; {$IFDEF _HE_} if sExcept <> gMgSvc.ModePolicy.MtpExcept then begin sExcept := gMgSvc.ModePolicy.MtpExcept; SplitString(sExcept, ';', IgrDevList); end; if sExceptVender <> gMgSvc.ModePolicy.MtpExceptVender then begin sExceptVender := gMgSvc.ModePolicy.MtpExceptVender; SplitString(UpperCase(sExceptVender), ';', IgrDevVdList); end; MtpBlockKind := gMgSvc.ModePolicy.MtpBlockKind; {$ENDIF} // 차단 실패 시 재시도 추가 23_0323 09:54:17 kku if BlockMtpList_.Count > 0 then begin for i := BlockMtpList_.Count - 1 downto 0 do begin pBlockEnt := BlockMtpList_[i]; pEnt := MgMtp_.GetMtpEntByDevId(pBlockEnt.sDevId); if pEnt = nil then begin BlockMtpList_.Delete(i); continue; end; sData := pEnt.sName + '|' + pEnt.sDesc + '|' + pEnt.sDevId; bPrevent := RemoveUsbDevEnableByDevPath(pEnt.sDevId) < 2; if bPrevent then begin sData := sData + '|PV'; gMgSvc.SendEventLog(URI_USER_ACTION, LOGCODE_PREVENT_MTP, Format('Name : %s, Desc : %s, Serial : %s', [pEnt.sName, pEnt.sDesc, pEnt.sDevId])); if gMgSvc.ModePolicy.MTPPopup then gMgSvc.PopupMessage(TYPE_MSG_PREVENT_MTP, sData); end else begin Inc(pBlockEnt.nTryCnt); _Trace('Fail .. BlockMTP, TryCnt=%d, DevId="%s"', [pBlockEnt.nTryCnt, pEnt.sDevId]); if pBlockEnt.nTryCnt >= 30 then // 4번에서 30번으로 변경 23_0329 14:51:07 kku begin BlockMtpList_.Delete(i); gMgSvc.SendEventLog(URI_USER_ACTION, LOGCODE_EVENT_MTP, Format('BF > Name : %s, Desc : %s, Serial : %s', [pEnt.sName, pEnt.sDesc, pEnt.sDevId]), false); if IsDivPopup then begin if gMgSvc.ModePolicy.MtpAllowPopup then gMgSvc.PopupMessage(TYPE_MSG_PREVENT_MTP, sData); end else gMgSvc.PopupMessage(TYPE_MSG_PREVENT_MTP, sData); end; end; end; end; ProcessMtpDev(MtpBlockKind, ChkMgMtp); FreeAndNil(MgMtp_); MgMtp_ := ChkMgMtp; ChkMgMtp := nil; except on E: Exception do ETgException.TraceException(Self, E, 'Fail .. Execute()'); end; Sleep(1000); end; finally if ChkMgMtp <> nil then FreeAndNil(ChkMgMtp); end; end; end.