{*******************************************************} { } { BS1Hook } { } { Copyright (C) 2022 kku } { } {*******************************************************} unit BS1Hook; interface uses System.SysUtils, System.Classes, Tocsg.DllEntry, Tocsg.CommonData, Winapi.Windows, Winapi.Messages, Winapi.ShellAPI, Tocsg.Trace, System.Generics.Collections, Tocsg.DRM.Encrypt, Vcl.Graphics, AppCtrlDefine, AppHookClient, GlobalDefine, System.SyncObjs, Tocsg.Thread; type PWebLogEnt = ^TWebLogEnt; TWebLogEnt = record dwTick: DWORD; sPath: String; nFType: Integer; bPrevent: Boolean; end; TThdWebABLog = class(TTgThread) protected sModuleName_: String; EntList_: TList; procedure OnEntNotify(Sender: TObject; const Item: PWebLogEnt; Action: TCollectionNotification); procedure Execute; override; public Constructor Create; Destructor Destroy; override; procedure Add(sPath: String; nFType: Integer; bPrevent: Boolean); procedure Del(nIdx: Integer); function IndexOf(sPath: String): Integer; procedure FindDel(sPath: String); end; TBS1Hook = class(TTgDllEntry) private CS_: TCriticalSection; dtCreate_: TDateTime; ProcList_: TList; Helper_: TAppCtrlHelper; Client_: TAppHookClient; Trace_: TTgTrace; bInitDrm_: Boolean; DrmFList_: TStringList; DocExtList_: TStringList; CapBlockWndList_: TList; RFileList_: TStringList; // 프린트 마스킹 PrtMaskList_: TStringList; procedure InitDrmProcess; procedure AddInterceptAPI(var aProcDest: Pointer; aProcSrc, aProcHook: Pointer; sProcName: String); procedure OnBeforeLog(Sender: TObject); procedure OnAfterLog(Sender: TObject); procedure Lock; procedure Unlock; procedure OnWebLogTimer(aSender: TObject); procedure OnWebLogEntNotify(Sender: TObject; const Item: PWebLogEnt; Action: TCollectionNotification); public // 전역 옵션 _bLogProcessing, _bInternalOpen: Boolean; sLogPath_: String; _hMTP: THandle; _sMtpDev: String; _dwMtpTick: DWORD; // MTP 인지하고 연속 차단을 위한 타임아웃 24_0604 16:19:01 kku // 브라우저 파일 차단 - 로그 ThdWebABLog: TThdWebABLog; // TimerWebABLog: TTimer; // WebLogEntList_: TList; Constructor Create; Destructor Destroy; override; procedure OnAppDisconnected(aSener: TObject); procedure AddWebABLog(sPath: String); procedure DelWebABLog(sPath: String); procedure AddCapBlockWnd(h: HWND); procedure DelCapBlockWnd(h: HWND); procedure ClearCapBlockWnd; procedure Log(sLog: String); overload; procedure Log(const sFormat: string; const Args: array of const); overload; procedure ProcessAppCtrlOpt(aOpt: TAppCtrlOpt); procedure ProcessNoti(nNotiCode: Integer; sPath: String; nFType: Integer; bDirect: Boolean = false); procedure DoInterceptRemove; procedure AddCreateFile(hFile: THandle; sPath: String); procedure DelCloseFile(hFile: THandle); function GetRFilePath(sFName: String): String; property Helper: TAppCtrlHelper read Helper_; property PrtMaskList: TStringList read PrtMaskList_; property DocExtList: TStringList read DocExtList_; end; var gAppHook: TBS1Hook = nil; implementation //{$DEFINE USE_BOXAPP} uses {$IFDEF USE_BOXAPP} BoxedAppSDK_Static, {$ENDIF} Condition, // BoxedAppSDK_DLL, DDetours, Tocsg.Safe, Tocsg.Path, Tocsg.Strings, Tocsg.Exception, DefineHelper, ApiHookFile, ApiHookPrint, ApiHookDraw, Tocsg.Packet, Tocsg.Process, Tocsg.Registry, ApiHookExplorer; { TThdWebABLog } Constructor TThdWebABLog.Create; begin Inherited Create; sModuleName_ := gAppHook.ModuleName; // FreeOnTerminate := true; EntList_ := TList.Create; EntList_.OnNotify := OnEntNotify; end; Destructor TThdWebABLog.Destroy; begin FreeAndNil(EntList_); Inherited; end; procedure TThdWebABLog.OnEntNotify(Sender: TObject; const Item: PWebLogEnt; Action: TCollectionNotification); begin try if Action = cnRemoved then Dispose(Item); except end; end; procedure TThdWebABLog.Add(sPath: String; nFType: Integer; bPrevent: Boolean); var pEnt: PWebLogEnt; begin try New(pEnt); pEnt.dwTick := GetTickCount; pEnt.sPath := sPath; pEnt.bPrevent := bPrevent; pEnt.nFType := nFType; Lock; try EntList_.Add(pEnt); finally Unlock; end; except // .. end; end; procedure TThdWebABLog.Del(nIdx: Integer); begin try Lock; try if (nIdx >= 0) and (EntList_.Count > nIdx) then EntList_.Delete(nIdx); finally Unlock; end; except // .. end; end; function TThdWebABLog.IndexOf(sPath: String): Integer; var i: Integer; begin Result := -1; try Lock; try for i := 0 to EntList_.Count - 1 do begin if EntList_[i].sPath = sPath then begin Result := i; exit; end; end; finally Unlock; end; except // .. end; end; procedure TThdWebABLog.FindDel(sPath: String); var i: Integer; begin try Lock; try for i := 0 to EntList_.Count - 1 do begin if EntList_[i].sPath = sPath then begin EntList_.Delete(i); exit; end; end; finally Unlock; end; except // .. end; end; procedure TThdWebABLog.Execute; var pEnt: PWebLogEnt; h: HWND; sPName: String; begin while not Terminated and not GetWorkStop do begin try Lock; try if EntList_.Count > 0 then pEnt := EntList_[0] else pEnt := nil; finally Unlock; end; if pEnt <> nil then begin if (GetTickCount - pEnt.dwTick) > 1000 then begin h := GetForegroundWindow; sPName := GetProcessNameFromWndHandle(h); if CompareText(sModuleName_, sPName) = 0 then begin if pEnt.bPrevent then gAppHook.ProcessNoti(NOTI_HOOK_BLOCK_ATTACH, pEnt.sPath, pEnt.nFType, true) else gAppHook.ProcessNoti(NOTI_HOOK_MONITOR_ATTACH, pEnt.sPath, pEnt.nFType, true); end; EntList_.Delete(0); end; end; Sleep(100); except // .. end; end; end; { TBS1Hook } Constructor TBS1Hook.Create; procedure GetStartTime; var ftCreate, ftExit, ftKernel, ftUser: TFileTime; nDosTime: Integer; begin dtCreate_ := 0; GetProcessTimes(GetCurrentProcess, ftCreate, ftExit, ftKernel, ftUser); if FileTimeToLocalFileTime(ftCreate, ftCreate) then if FileTimeToDosDateTime(ftCreate, LongRec(nDosTime).Hi, LongRec(nDosTime).Lo) then dtCreate_ := FileDateToDateTime(nDosTime); end; var IgrList: TStringList; DrmInitInfo: TTgFileMapping; CtrlOpt: TAppCtrlOpt; begin Inherited Create; ASSERT(gAppHook = nil); gAppHook := Self; CS_ := TCriticalSection.Create; sLogPath_ := ''; _bLogProcessing := false; _bInternalOpen := false; _hMTP := 0; _sMtpDev := ''; _dwMtpTick := 0; bInitDrm_ := false; GetStartTime; ThdWebABLog := nil; // TimerWebABLog := nil; // WebLogEntList_ := nil; PrtMaskList_ := TStringList.Create; RFileList_ := TStringList.Create; RFileList_.CaseSensitive := false; Trace_ := nil; //{$IFDEF DEBUG} // 이거 켜면 DLL 해제 시 떨어지지 않는다 23_0315 11:09:49 kku // sLogPath_ := 'C:\taskToCSG\Tocsg.Module\AppCtrl\OUT_Debug - Win64\AppCtrl.log'; //// if FileExists(sLogPath_) then //// DeleteFile(PChar(sLogPath_)); // Trace_ := TTgTrace.Create(ExtractFilePath(sLogPath_), ExtractFileName(sLogPath_)); // Trace_.OnBeforeLog := OnBeforeLog; // Trace_.OnAfterLog := OnAfterLog; // Trace_.LoadHead := ModuleName + ' > '; //{$ENDIF} CapBlockWndList_ := TList.Create; DrmFList_ := TStringList.Create; DrmFList_.CaseSensitive := false; DocExtList_ := TStringList.Create; DocExtList_.CaseSensitive := false; SplitString('TXT|DOC|PDF|XLS|PPT|HWP|HWPX|DOCX|DOTX|XLSX|XLTX|PPTX|POTX', '|', DocExtList_); ProcList_ := TList.Create; Helper_ := TAppCtrlHelper.Create(ModulePath); if Helper_.CurAppType = catWebb then begin // ThdWebABLog := TThdWebABLog.Create; // ThdWebABLog.StartThread; // Sleep(2000); // FreeAndNil(ThdWebABLog); end; if Helper_.IsDrmSupport then begin ZeroMemory(@CtrlOpt, SizeOf(CtrlOpt)); // DRM 처리 정보는 프로세스 접속 해서 정책 받기 전에 미리 받아야 한다. 그래서 앞서 별도 처리함 23_0317 13:12:50 kku Guard(DrmInitInfo, TTgFileMapping.Create(MAP_FILENAME_APIHOOK, SizeOf(TDrmInfo))); if DrmInitInfo.IsAvailable then begin CtrlOpt.dwCustomerType := DrmInitInfo.Data.dwCustomerType; CtrlOpt.DrmAccessKind := DrmInitInfo.Data.DrmAccessKind; CtrlOpt.DrmModifyKind := DrmInitInfo.Data.DrmModifyKind; CtrlOpt.sTaskDir := StrPas(DrmInitInfo.Data.sTaskDir); CtrlOpt.sDrmPass := StrPas(DrmInitInfo.Data.sDrmPass); CtrlOpt.sEmpNo := StrPas(DrmInitInfo.Data.sEmpNo); CtrlOpt.sDeptName := StrPas(DrmInitInfo.Data.sDeptName); end else begin _Trace('Fail .. Create() .. OpenFileMapping()'); end; if CtrlOpt.sDrmPass <> '' then CtrlOpt.sDrmPass := DecText(CtrlOpt.sDrmPass); Helper_.CtrlOpt := CtrlOpt; end; if CtrlOpt.dwCustomerType = CUSTOMER_KOCES then begin Helper_.NoDrmUse; // SetErrorMode(SEM_NOGPFAULTERRORBOX); // 시스템 에러 씹기 23_0330 11:21:25 kku end; Client_ := TAppHookClient.Create; if Helper_.CurAppType = catkvHelper then begin ZeroMemory(@CtrlOpt, SizeOf(CtrlOpt)); CtrlOpt.bPrintSecu := true; CtrlOpt.bPrintWater := true; CtrlOpt.dwCustomerType := GetRegValueAsInteger(HKEY_CURRENT_USER, REG_HE, 'CT'); CtrlOpt.sUName := GetRegValueAsString(HKEY_CURRENT_USER, REG_HE, 'UName'); CtrlOpt.sEmpNo := GetRegValueAsString(HKEY_CURRENT_USER, REG_HE, 'EmpNo'); CtrlOpt.sDeptName := GetRegValueAsString(HKEY_CURRENT_USER, REG_HE, 'DeptName'); CtrlOpt.fWmTran := StrToFloatDef(GetRegValueAsString(HKEY_CURRENT_USER, REG_HE, 'WmTran'), 0.0); Helper_.CtrlOpt := CtrlOpt; // LogToReg('kvcttsch.exe_Load', 'MName = ' + ModuleName); // LogToReg('kvcttsch.exe_Load', 'dwCustomerType = ' + IntToStr(Helper_.CtrlOpt.dwCustomerType)); AddInterceptAPI(@ozCreateDC, @CreateDC, @CreateDCHook, 'CreateDC'); AddInterceptAPI(@ozCreateDCA, @CreateDCA, @CreateDCAHook, 'CreateDCA'); AddInterceptAPI(@ozCreateDCW, @CreateDCW, @CreateDCWHook, 'CreateDCW'); AddInterceptAPI(@ozStartDocA, @StartDocA, @StartDocAHook, 'StartDocA'); AddInterceptAPI(@ozStartDocW, @StartDocW, @StartDocWHook, 'StartDocW'); AddInterceptAPI(@ozStartPage, @StartPage, @StartPageHook, 'StartPage'); AddInterceptAPI(@ozEndPage, @EndPage, @EndPageHook, 'EndPage'); AddInterceptAPI(@ozEndDoc, @EndDoc, @EndDocHook, 'EndDoc'); // AddInterceptAPI(@ozWritePrinter, @WritePrinter, @WritePrinterHook, 'WritePrinter'); end else begin Client_.OnDisconnected := OnAppDisconnected; Client_.TryReconnect := true; Client_.ModulePath := ModulePath; if not Client_.ActiveNp('BS1@230316', false) then begin Log('Fail .. ActiveNp()'); exit; end; if not Client_.ConnectNp then begin Log('Fail .. Connection'); exit; end; end; if Helper_.IsDrmSupport and (CtrlOpt.DrmAccessKind <> dakNone) then InitDrmProcess; Log('Create() ..'); end; Destructor TBS1Hook.Destroy; begin gAppHook := nil; if ThdWebABLog <> nil then begin ThdWebABLog.PauseThread; // 이렇게 안하고 FreeAndNil() 하면 브라우저가 뻗음 24_0408 14:06:40 kku // ThdWebABLog.StopThread; // ThdWebABLog.Terminate; // FreeAndNil(ThdWebABLog); // ThdWebABLog := nil; end; // FreeAndNil(Helper_); // 이거 살리면 떼어낼때 대상 프로그램이 죽는경우가 생긴다..24_0408 10:00:24 kku ClearCapBlockWnd; DoInterceptRemove; FreeAndNil(ProcList_); FreeAndNil(DrmFList_); FreeAndNil(CapBlockWndList_); if Trace_ <> nil then FreeAndNil(Trace_); FreeAndNil(RFileList_); FreeAndNil(PrtMaskList_); Inherited; // if TimerWebABLog <> nil then // FreeAndNil(TimerWebABLog); // if WebLogEntList_ <> nil then // FreeAndNIl(WebLogEntList_); FreeAndNil(CS_); end; procedure TBS1Hook.OnAppDisconnected(aSener: TObject); var CtrlOpt: TAppCtrlOpt; begin ZeroMemory(@CtrlOpt, SizeOf(CtrlOpt)); Helper_.CtrlOpt := CtrlOpt; end; procedure TBS1Hook.OnWebLogEntNotify(Sender: TObject; const Item: PWebLogEnt; Action: TCollectionNotification); begin if Action = cnRemoved then Dispose(Item); end; procedure TBS1Hook.AddWebABLog(sPath: String); var pEnt: PWebLogEnt; begin // if TimerWebABLog = nil then // begin // WebLogEntList_ := TList.Create; // WebLogEntList_.OnNotify := OnWebLogEntNotify; // // TimerWebABLog := TTimer.Create(nil); // TimerWebABLog.OnTimer := OnWebLogTimer; // TimerWebABLog.Interval := 200; // TimerWebABLog.Enabled := true; // end; // // New(pEnt); // pEnt.dwTick := GetTickCount; // pEnt.sPath := sPath; // WebLogEntList_.Add(pEnt); end; procedure TBS1Hook.DelWebABLog(sPath: String); var i: Integer; begin // if WebLogEntList_ <> nil then // begin // for i := 0 to WebLogEntList_.Count - 1 do // begin // if WebLogEntList_[i].sPath = sPath then // begin // WebLogEntList_.Delete(i); // exit; // end; // end; // end; end; procedure TBS1Hook.OnWebLogTimer(aSender: TObject); var pEnt: PWebLogEnt; begin // if WebLogEntList_ = nil then // exit; // // try // if WebLogEntList_.Count > 0 then // pEnt := WebLogEntList_[0] // else // pEnt := nil; // // if pEnt <> nil then // begin // if (GetTickCount - pEnt.dwTick) > 1000 then // begin // gAppHook.ProcessNoti(NOTI_HOOK_MONITOR_ATTACH, pEnt.sPath); // WebLogEntList_.Delete(0); // end; // end; // except // // .. // end; end; procedure TBS1Hook.OnBeforeLog(Sender: TObject); begin _bLogProcessing := true; end; procedure TBS1Hook.OnAfterLog(Sender: TObject); begin _bLogProcessing := false; end; procedure TBS1Hook.Lock; begin CS_.Acquire; end; procedure TBS1Hook.Unlock; begin CS_.Release; end; procedure TBS1Hook.AddCapBlockWnd(h: HWND); begin try if h = 0 then exit; if CapBlockWndList_.IndexOf(h) = -1 then CapBlockWndList_.Add(h); SetWindowDisplayAffinity(h, 1); except // .. end; end; procedure TBS1Hook.DelCapBlockWnd(h: HWND); begin try if h = 0 then exit; if CapBlockWndList_.IndexOf(h) <> -1 then SetWindowDisplayAffinity(h, 0); except // .. end; end; procedure TBS1Hook.ClearCapBlockWnd; var i: Integer; begin try if CapBlockWndList_.Count = 0 then exit; for i := 0 to CapBlockWndList_.Count - 1 do SetWindowDisplayAffinity(CapBlockWndList_[i], 0); CapBlockWndList_.Clear; except // .. end; end; procedure TBS1Hook.InitDrmProcess; {$IFDEF USE_BOXAPP} var bLoadBx: Boolean; Label LB_LoadBx; {$ENDIF} begin if not bInitDrm_ then begin Log('InitDrmProcess() ..'); {$IFDEF USE_BOXAPP} // if bUseBoxedApp_ then begin try bLoadBx := false; LB_LoadBx : try // Init BoxedApp SDK BoxedAppSDK_SetContext('21f2f010-06e4-465f-af8f-cde6a3752c39'); BoxedAppSDK_Init; // Allow injection BoxedApp engine into child processes // BoxedAppSDK_EnableOption(DEF_BOXEDAPPSDK_OPTION__EMBED_BOXEDAPP_IN_CHILD_PROCESSES, TRUE); // BoxedAppSDK_EnableOption(DEF_BOXEDAPPSDK_OPTION__HIDE_VIRTUAL_FILES_FROM_FILE_DIALOG, TRUE); // BoxedAppSDK_EnableOption(DEF_BOXEDAPPSDK_OPTION__ALL_CHANGES_ARE_VIRTUAL, TRUE); bLoadBx := true; except Log('Fail .. BoxedAppSDK'); end; if not bLoadBx then begin Sleep(10); goto LB_LoadBx; end; except Log('Fail .. UseBoxedAppSDK'); end; end; {$ENDIF} AddInterceptAPI(@ozCreateFileA, @CreateFileA, @CreateFileAHook, 'CreateFileA'); AddInterceptAPI(@ozCreateFileW, @CreateFileW, @CreateFileWHook, 'CreateFileW'); AddInterceptAPI(@ozCloseHandle, @CloseHandle, @CloseHandleHook, 'CloseHandle'); bInitDrm_ := true; end; end; procedure TBS1Hook.ProcessAppCtrlOpt(aOpt: TAppCtrlOpt); begin try if CompareText(ModuleName, EXE_HE) = 0 then begin var CtrlOpt: TAppCtrlOpt; ZeroMemory(@CtrlOpt, SizeOf(CtrlOpt)); CtrlOpt.bPrintSecu := true; CtrlOpt.bPrintWater := true; CtrlOpt.dwCustomerType := aOpt.dwCustomerType; CtrlOpt.sUName := aOpt.sUName; CtrlOpt.sEmpNo := aOpt.sEmpNo; CtrlOpt.sDeptName := aOpt.sDeptName; Helper_.CtrlOpt := CtrlOpt; // LogToReg('kvcttsch.exe_Load', 'MName = ' + ModuleName); AddInterceptAPI(@ozCreateDC, @CreateDC, @CreateDCHook, 'CreateDC'); AddInterceptAPI(@ozCreateDCA, @CreateDCA, @CreateDCAHook, 'CreateDCA'); AddInterceptAPI(@ozCreateDCW, @CreateDCW, @CreateDCWHook, 'CreateDCW'); AddInterceptAPI(@ozStartDocA, @StartDocA, @StartDocAHook, 'StartDocA'); AddInterceptAPI(@ozStartDocW, @StartDocW, @StartDocWHook, 'StartDocW'); AddInterceptAPI(@ozStartPage, @StartPage, @StartPageHook, 'StartPage'); AddInterceptAPI(@ozEndPage, @EndPage, @EndPageHook, 'EndPage'); AddInterceptAPI(@ozEndDoc, @EndDoc, @EndDocHook, 'EndDoc'); exit; end; // DoInterceptRemove; aOpt.bMtpWB := aOpt.bMtpWB and (Helper_.CurAppType = catExplorer); // 탐색기에서만 활성화 되도록 24_0604 15:23:45 kku if aOpt.dwCustomerType = CUSTOMER_KOCES then begin Helper_.NoDrmUse; Helper_.bEndDocProc_ := CompareText('excel.exe', ModuleName) <> 0; // 엑셀에서 이렇게 하면 워터마크가 뒤로 밀리는 문제가 있음..23_0410 15:52:34 kku end; if Helper_.CurAppType <> catWebb then // 브라우저는 실시간으로 적용/해제 하고 있어서 여기서 처리하지 않음 25_1113 15:12:01 kku begin if (aOpt.hCltWnd <> 0) and (CapBlockWndList_.Count = 0) then begin // 화면 캡쳐 차단 설정 AddCapBlockWnd(aOpt.hCltWnd); end else if (aOpt.hCltWnd = 0) and (CapBlockWndList_.Count <> 0) then begin // 화면 캡쳐 차단 해제 ClearCapBlockWnd; end; end; if aOpt.sDrmPass <> '' then aOpt.sDrmPass := DecText(aOpt.sDrmPass); Helper_.CtrlOpt := aOpt; if Helper_.IsDrmSupport and (aOpt.DrmAccessKind <> dakNone) and not bInitDrm_ then InitDrmProcess; if (aOpt.FileUseBlock <> fubNone) or (aOpt.bMtpWB and (Helper_.CurAppType = catExplorer)) then begin AddInterceptAPI(@ozCreateFileA, @CreateFileA, @CreateFileAHook, 'CreateFileA'); AddInterceptAPI(@ozCreateFileW, @CreateFileW, @CreateFileWHook, 'CreateFileW'); end; if Helper_.CurAppType = catExplorer then begin if aOpt.ShFileCrMon.nKind <> 0 then begin SplitString(UpperCase(Helper_.CtrlOpt.ShFileCrMon.sExpLst), '|', Helper_.FoExpList, false, true); InstallFileOperationHooks; end else UninstallFileOperationHooks; end; if (Helper_.CurAppType <> catExplorer) and (aOpt.bPrintSecu or aOpt.bPrintWater) then begin AddInterceptAPI(@ozCreateDC, @CreateDC, @CreateDCHook, 'CreateDC'); AddInterceptAPI(@ozCreateDCA, @CreateDCA, @CreateDCAHook, 'CreateDCA'); AddInterceptAPI(@ozCreateDCW, @CreateDCW, @CreateDCWHook, 'CreateDCW'); AddInterceptAPI(@ozStartDocA, @StartDocA, @StartDocAHook, 'StartDocA'); AddInterceptAPI(@ozStartDocW, @StartDocW, @StartDocWHook, 'StartDocW'); AddInterceptAPI(@ozStartPage, @StartPage, @StartPageHook, 'StartPage'); AddInterceptAPI(@ozEndPage, @EndPage, @EndPageHook, 'EndPage'); AddInterceptAPI(@ozEndDoc, @EndDoc, @EndDocHook, 'EndDoc'); if (Helper_.CurAppType <> catkvHelper) and aOpt.bPrtCollect and (aOpt.sPrtEmfOutDir <> '') then begin AddInterceptAPI(@ozExtTextOutA, @ExtTextOutA, @ExtTextOutAHook, 'ExtTextOutA'); // notepad++ AddInterceptAPI(@ozExtTextOutW, @ExtTextOutW, @ExtTextOutWHook, 'ExtTextOutW'); // notepad++ AddInterceptAPI(@ozSetWorldTransform, @SetWorldTransform, @SetWorldTransformHook, 'SetWorldTransform'); // 좌표값 추출 AddInterceptAPI(@ozModifyWorldTransform, @ModifyWorldTransform, @ModifyWorldTransformHook, 'ModifyWorldTransform'); // 좌표값 추출, 이거 켜면 PPT에서 텍스트 위치가 꼬인다 25_1001 22:00:24 kku AddInterceptAPI(@ozRectangle, @Rectangle, @RectangleHook, 'Rectangle'); AddInterceptAPI(@ozSelectObject, @SelectObject, @SelectObjectHook, 'SelectObject'); AddInterceptAPI(@ozStretchDIBits, @StretchDIBits, @StretchDIBitsHook, 'StretchDIBits'); // chrome 필수 AddInterceptAPI(@ozSetStretchBltMode, @SetStretchBltMode, @SetStretchBltModeHook, 'SetStretchBltMode'); AddInterceptAPI(@ozSetPolyFillMode, @SetPolyFillMode, @SetPolyFillModeHook, 'SetPolyFillMode'); AddInterceptAPI(@ozBeginPath, @BeginPath, @BeginPathHook, 'BeginPath'); // chrome 필수 AddInterceptAPI(@ozMoveToEx, @MoveToEx, @MoveToExHook, 'MoveToEx'); // chrome 필수 AddInterceptAPI(@ozPolyBezierTo, @PolyBezierTo, @PolyBezierToHook, 'PolyBezierTo'); // chrome 필수 AddInterceptAPI(@ozLineTo, @LineTo, @LineToHook, 'LineTo'); // chrome 필수 AddInterceptAPI(@ozCloseFigure, @CloseFigure, @CloseFigureHook, 'CloseFigure'); AddInterceptAPI(@ozEndPath, @EndPath, @EndPathHook, 'EndPath'); // chrome 필수 AddInterceptAPI(@ozFillPath, @FillPath, @FillPathHook, 'FillPath'); // chrome 필수 AddInterceptAPI(@ozLPtoDP, @LPtoDP, @LPtoDPHook, 'LPtoDP'); AddInterceptAPI(@ozDPtoLP, @DPtoLP, @DPtoLPHook, 'DPtoLP'); AddInterceptAPI(@ozFillRect, @FillRect, @FillRectHook, 'FillRect'); AddInterceptAPI(@ozRestoreDC, @RestoreDC, @RestoreDCHook, 'RestoreDC'); AddInterceptAPI(@ozSaveDC, @SaveDC, @SaveDCHook, 'SaveDC'); AddInterceptAPI(@ozIntersectClipRect, @IntersectClipRect, @IntersectClipRectHook, 'IntersectClipRect'); AddInterceptAPI(@ozBitBlt, @BitBlt, @BitBltHook, 'BitBlt'); AddInterceptAPI(@ozSetPixel, @SetPixel, @SetPixelHook, 'SetPixel'); AddInterceptAPI(@ozPlgBlt, @PlgBlt, @PlgBltHook, 'PlgBlt'); AddInterceptAPI(@ozPatBlt, @PatBlt, @PatBltHook, 'PatBlt'); AddInterceptAPI(@ozStretchBlt, @StretchBlt, @StretchBltHook, 'StretchBlt'); AddInterceptAPI(@ozEllipse, @Ellipse, @EllipseHook, 'Ellipse'); AddInterceptAPI(@ozTextOutA, @TextOutA, @TextOutAHook, 'TextOutA'); AddInterceptAPI(@ozTextOutW, @TextOutW, @TextOutWHook, 'TextOutW'); AddInterceptAPI(@ozSetTextAlign, @SetTextAlign, @SetTextAlignHook, 'SetTextAlign'); AddInterceptAPI(@ozSetBkMode, @SetBkMode, @SetBkModeHook, 'SetBkMode'); AddInterceptAPI(@ozSetViewportOrgEx, @SetViewportOrgEx, @SetViewportOrgExHook, 'SetViewportOrgEx'); AddInterceptAPI(@ozExtSelectClipRgn, @ExtSelectClipRgn, @ExtSelectClipRgnHook, 'ExtSelectClipRgn'); AddInterceptAPI(@ozSelectClipRgn, @SelectClipRgn, @SelectClipRgnHook, 'SelectClipRgn'); AddInterceptAPI(@ozSetMapMode, @SetMapMode, @SetMapModeHook, 'SetMapMode'); AddInterceptAPI(@ozSetWindowOrgEx, @SetWindowOrgEx, @SetWindowOrgExHook, 'SetWindowOrgEx'); AddInterceptAPI(@ozSelectPalette, @SelectPalette, @SelectPaletteHook, 'SelectPalette'); AddInterceptAPI(@ozSetGraphicsMode, @SetGraphicsMode, @SetGraphicsModeHook, 'SetGraphicsMode'); AddInterceptAPI(@ozSetBkColor, @SetBkColor, @SetBkColorHook, 'SetBkColor'); AddInterceptAPI(@ozSetBrushOrgEx, @SetBrushOrgEx, @SetBrushOrgExHook, 'SetBrushOrgEx'); AddInterceptAPI(@ozSetDIBits, @SetDIBits, @SetDIBitsHook, 'SetDIBits'); AddInterceptAPI(@ozSetROP2, @SetROP2, @SetROP2Hook, 'SetROP2'); AddInterceptAPI(@ozSetColorSpace, @SetColorSpace, @SetColorSpaceHook, 'SetColorSpace'); AddInterceptAPI(@ozExcludeClipRect, @ExcludeClipRect, @ExcludeClipRectHook, 'ExcludeClipRect'); AddInterceptAPI(@ozSetViewportExtEx, @SetViewportExtEx, @SetViewportExtExHook, 'SetViewportExtEx'); AddInterceptAPI(@ozSetWindowExtEx, @SetWindowExtEx, @SetWindowExtExHook, 'SetWindowExtEx'); AddInterceptAPI(@ozScaleViewportExtEx, @ScaleViewportExtEx, @ScaleViewportExtExHook, 'ScaleViewportExtEx'); AddInterceptAPI(@ozSetTextColor, @SetTextColor, @SetTextColorHook, 'SetTextColor'); AddInterceptAPI(@ozSetDCBrushColor, @SetDCBrushColor, @SetDCBrushColorHook, 'SetDCBrushColor'); AddInterceptAPI(@ozSetDCPenColor, @SetDCPenColor, @SetDCPenColorHook, 'SetDCPenColor'); AddInterceptAPI(@ozCreateHalftonePalette, @CreateHalftonePalette, @CreateHalftonePaletteHook, 'CreateHalftonePalette'); AddInterceptAPI(@ozCreateDIBSection, @CreateDIBSection, @CreateDIBSectionHook, 'CreateDIBSection'); AddInterceptAPI(@ozSetBoundsRect, @SetBoundsRect, @SetBoundsRectHook, 'SetBoundsRect'); AddInterceptAPI(@ozSetSystemPaletteUse, @SetSystemPaletteUse, @SetSystemPaletteUseHook, 'SetSystemPaletteUse'); AddInterceptAPI(@ozRealizePalette, @RealizePalette, @RealizePaletteHook, 'RealizePalette'); AddInterceptAPI(@ozSetDIBColorTable, @SetDIBColorTable, @SetDIBColorTableHook, 'SetDIBColorTable'); AddInterceptAPI(@ozSetMapperFlags, @SetMapperFlags, @SetMapperFlagsHook, 'SetMapperFlags'); AddInterceptAPI(@ozSetColorAdjustment, @SetColorAdjustment, @SetColorAdjustmentHook, 'SetColorAdjustment'); AddInterceptAPI(@ozPolyBezier, @PolyBezier, @PolyBezierHook, 'PolyBezier'); AddInterceptAPI(@ozPolygon, @Polygon, @PolygonHook, 'Polygon'); AddInterceptAPI(@ozPolyline, @Polyline, @PolylineHook, 'Polyline'); AddInterceptAPI(@ozPolyLineTo, @PolyLineTo, @PolyLineToHook, 'PolyLineTo'); AddInterceptAPI(@ozPolyPolyline, @PolyPolyline, @PolyPolylineHook, 'PolyPolyline'); AddInterceptAPI(@ozPolyPolygon, @PolyPolygon, @PolyPolygonHook, 'PolyPolygon'); AddInterceptAPI(@ozSetPixelV, @SetPixelV, @SetPixelVHook, 'SetPixelV'); AddInterceptAPI(@ozColorCorrectPalette, @ColorCorrectPalette, @ColorCorrectPaletteHook, 'ColorCorrectPalette'); AddInterceptAPI(@ozSetICMProfileA, @SetICMProfileA, @SetICMProfileAHook, 'SetICMProfileA'); AddInterceptAPI(@ozSetICMProfileW, @SetICMProfileW, @SetICMProfileWHook, 'SetICMProfileW'); AddInterceptAPI(@ozSetTextJustification, @SetTextJustification, @SetTextJustificationHook, 'SetTextJustification'); AddInterceptAPI(@ozScaleWindowExtEx, @ScaleWindowExtEx, @ScaleWindowExtExHook, 'ScaleWindowExtEx'); AddInterceptAPI(@ozAngleArc, @AngleArc, @AngleArcHook, 'AngleArc'); AddInterceptAPI(@ozRoundRect, @RoundRect, @RoundRectHook, 'RoundRect'); AddInterceptAPI(@ozArc, @Arc, @ArcHook, 'Arc'); AddInterceptAPI(@ozChord, @Chord, @ChordHook, 'Chord'); AddInterceptAPI(@ozPie, @Pie, @PieHook, 'Pie'); AddInterceptAPI(@ozExtFloodFill, @ExtFloodFill, @ExtFloodFillHook, 'ExtFloodFill'); AddInterceptAPI(@ozArcTo, @ArcTo, @ArcToHook, 'ArcTo'); AddInterceptAPI(@ozPolyDraw, @PolyDraw, @PolyDrawHook, 'PolyDraw'); AddInterceptAPI(@ozSetMiterLimit, @SetMiterLimit, @SetMiterLimitHook, 'SetMiterLimit'); AddInterceptAPI(@ozStrokeAndFillPath, @StrokeAndFillPath, @StrokeAndFillPathHook, 'StrokeAndFillPath'); AddInterceptAPI(@ozStrokePath, @StrokePath, @StrokePathHook, 'StrokePath'); AddInterceptAPI(@ozFlattenPath, @FlattenPath, @FlattenPathHook, 'FlattenPath'); AddInterceptAPI(@ozWidenPath, @WidenPath, @WidenPathHook, 'WidenPath'); AddInterceptAPI(@ozSelectClipPath, @SelectClipPath, @SelectClipPathHook, 'SelectClipPath'); AddInterceptAPI(@ozAbortPath, @AbortPath, @AbortPathHook, 'AbortPath'); AddInterceptAPI(@ozFillRgn, @FillRgn, @FillRgnHook, 'FillRgn'); AddInterceptAPI(@ozFrameRgn, @FrameRgn, @FrameRgnHook, 'FrameRgn'); AddInterceptAPI(@ozInvertRgn, @InvertRgn, @InvertRgnHook, 'InvertRgn'); AddInterceptAPI(@ozPaintRgn, @PaintRgn, @PaintRgnHook, 'PaintRgn'); AddInterceptAPI(@ozMaskBlt, @MaskBlt, @MaskBltHook, 'MaskBlt'); AddInterceptAPI(@ozPolyTextOutA, @PolyTextOutA, @PolyTextOutAHook, 'PolyTextOutA'); AddInterceptAPI(@ozPolyTextOutW, @PolyTextOutW, @PolyTextOutWHook, 'PolyTextOutW'); AddInterceptAPI(@ozUpdateColors, @UpdateColors, @UpdateColorsHook, 'UpdateColors'); AddInterceptAPI(@ozOffsetViewportOrgEx, @OffsetViewportOrgEx, @OffsetViewportOrgExHook, 'OffsetViewportOrgEx'); AddInterceptAPI(@ozOffsetWindowOrgEx, @OffsetWindowOrgEx, @OffsetWindowOrgExHook, 'OffsetWindowOrgEx'); AddInterceptAPI(@ozSetDeviceGammaRamp, @SetDeviceGammaRamp, @SetDeviceGammaRampHook, 'SetDeviceGammaRamp'); AddInterceptAPI(@ozColorMatchToTarget, @ColorMatchToTarget, @ColorMatchToTargetHook, 'ColorMatchToTarget'); AddInterceptAPI(@ozPtVisible, @PtVisible, @PtVisibleHook, 'PtVisible'); AddInterceptAPI(@ozRectVisible, @RectVisible, @RectVisibleHook, 'RectVisible'); AddInterceptAPI(@ozSetPixelFormat, @SetPixelFormat, @SetPixelFormatHook, 'SetPixelFormat'); AddInterceptAPI(@ozOffsetClipRgn, @OffsetClipRgn, @OffsetClipRgnHook, 'OffsetClipRgn'); AddInterceptAPI(@ozSetArcDirection, @SetArcDirection, @SetArcDirectionHook, 'SetArcDirection'); AddInterceptAPI(@ozSetTextCharacterExtra, @SetTextCharacterExtra, @SetTextCharacterExtraHook, 'SetTextCharacterExtra'); AddInterceptAPI(@ozEnumICMProfilesA, @EnumICMProfilesA, @EnumICMProfilesAHook, 'EnumICMProfilesA'); AddInterceptAPI(@ozEnumICMProfilesW, @EnumICMProfilesW, @EnumICMProfilesWHook, 'EnumICMProfilesW'); AddInterceptAPI(@ozSetICMMode, @SetICMMode, @SetICMModeHook, 'SetICMMode'); AddInterceptAPI(@ozSetDIBitsToDevice, @SetDIBitsToDevice, @SetDIBitsToDeviceHook, 'SetDIBitsToDevice'); AddInterceptAPI(@ozDrawEscape, @DrawEscape, @DrawEscapeHook, 'DrawEscape'); AddInterceptAPI(@ozEnumFontsA, @EnumFontsA, @EnumFontsAHook, 'EnumFontsA'); AddInterceptAPI(@ozEnumFontsW, @EnumFontsW, @EnumFontsWHook, 'EnumFontsW'); AddInterceptAPI(@ozEnumFontFamiliesA, @EnumFontFamiliesA, @EnumFontFamiliesAHook, 'EnumFontFamiliesA'); AddInterceptAPI(@ozEnumFontFamiliesW, @EnumFontFamiliesW, @EnumFontFamiliesWHook, 'EnumFontFamiliesW'); AddInterceptAPI(@ozSetMetaRgn, @SetMetaRgn, @SetMetaRgnHook, 'SetMetaRgn'); AddInterceptAPI(@ozPlayEnhMetaFile, @PlayEnhMetaFile, @PlayEnhMetaFileHook, 'PlayEnhMetaFile'); AddInterceptAPI(@ozPlayEnhMetaFileRecord, @PlayEnhMetaFileRecord, @PlayEnhMetaFileRecordHook, 'PlayEnhMetaFileRecord'); // AddInterceptAPI(@ozTransparentBlt, @TransparentBlt, @TransparentBltHook, 'TransparentBlt'); // AddInterceptAPI(@ozGradientFill, @GradientFill, @GradientFillHook, 'GradientFill'); // AddInterceptAPI(@ozFrameRect, @FrameRect, @FrameRectHook, 'FrameRect'); // AddInterceptAPI(@ozFloodFill, @FloodFill, @FloodFillHook, 'FloodFill'); // 훅 제외 // AddInterceptAPI(@ozDrawTextExA, @DrawTextExA, @DrawTextExAHook_DW, 'DrawTextExA'); // AddInterceptAPI(@ozDrawTextExW, @DrawTextExW, @DrawTextExWHook_DW, 'DrawTextExW'); // AddInterceptAPI(@ozTabbedTextOutA, @TabbedTextOutA, @TabbedTextOutAHook, 'TabbedTextOutA'); // AddInterceptAPI(@ozTabbedTextOutW, @TabbedTextOutW, @TabbedTextOutWHook, 'TabbedTextOutW'); // AddInterceptAPI(@ozGetTextCharsetInfo, @GetTextCharsetInfo, @GetTextCharsetInfoHook, 'GetTextCharsetInfo'); // 훅 제외 // AddInterceptAPI(@ozGetGlyphIndicesA, @GetGlyphIndicesA, @GetGlyphIndicesAHook, 'GetGlyphIndicesA') // 훅 제외; // AddInterceptAPI(@ozGetGlyphIndicesW, @GetGlyphIndicesW, @GetGlyphIndicesWHook, 'GetGlyphIndicesW'); // 훅 제외 // AddInterceptAPI(@ozGetFontLanguageInfo, @GetFontLanguageInfo, @GetFontLanguageInfoHook, 'GetFontLanguageInfo'); // 훅 제외 // AddInterceptAPI(@ozGetCharacterPlacementA, @GetCharacterPlacementA, @GetCharacterPlacementAHook, 'GetCharacterPlacementA'); // 훅 제외 // AddInterceptAPI(@ozGetCharacterPlacementW, @GetCharacterPlacementW, @GetCharacterPlacementWHook, 'GetCharacterPlacementW'); // 훅 제외 // AddInterceptAPI(@ozGetFontData, @GetFontData, @GetFontDataHook, 'GetFontData'); // 훅 제외 // AddInterceptAPI(@ozGetGlyphOutlineA, @GetGlyphOutlineA, @GetGlyphOutlineAHook, 'GetGlyphOutlineA'); // 훅 제외 // AddInterceptAPI(@ozGetGlyphOutlineW, @GetGlyphOutlineW, @GetGlyphOutlineWHook, 'GetGlyphOutlineW'); // 훅 제외 // AddInterceptAPI(@ozResetDCA, @ResetDCA, @ResetDCAHook, 'ResetDCA'); // 사용하지 않음 // AddInterceptAPI(@ozResetDCW, @ResetDCW, @ResetDCWHook, 'ResetDCW'); // 사용하지 않음 // AddInterceptAPI(@ozAlphaBlend, @AlphaBlend, @AlphaBlendHook, 'AlphaBlend'); // 훅 제외 // AddInterceptAPI(@ozGetTextMetricsA, @GetTextMetricsA, @GetTextMetricsAHook, 'GetTextMetricsA'); // 훅 제외 // AddInterceptAPI(@ozGetTextMetricsW, @GetTextMetricsW, @GetTextMetricsWHook, 'GetTextMetricsW'); // 훅 제외 // AddInterceptAPI(@ozGetTextExtentPoint32A, @GetTextExtentPoint32A, @GetTextExtentPoint32AHook, 'GetTextExtentPoint32A'); // 훅 제외 // AddInterceptAPI(@ozGetTextExtentPoint32W, @GetTextExtentPoint32W, @GetTextExtentPoint32WHook, 'GetTextExtentPoint32W'); // 훅 제외 // AddInterceptAPI(@ozGdiComment, @GdiComment, @GdiCommentHook, 'GdiComment'); // 훅 제외 // AddInterceptAPI(@ozGetCharABCWidthsA, @GetCharABCWidthsA, @GetCharABCWidthsAHook, 'GetCharABCWidthsA'); // 훅 제외 // AddInterceptAPI(@ozGetCharABCWidthsW, @GetCharABCWidthsW, @GetCharABCWidthsWHook, 'GetCharABCWidthsW'); // 훅 제외 // AddInterceptAPI(@ozExtEscape, @ExtEscape, @ExtEscapeHook, 'ExtEscape'); // 훅 제외 // AddInterceptAPI(@ozCreateCompatibleDC, @CreateCompatibleDC, @CreateCompatibleDCHook, 'CreateCompatibleDC'); // 훅 제외 // AddInterceptAPI(@ozCreateCompatibleBitmap, @CreateCompatibleBitmap, @CreateCompatibleBitmapHook, 'CreateCompatibleBitmap'); // 훅 제외 // 이거 활성화 하면 프린트 창이 안뜨고 죽는다 25_1001 19:27:29 kku // AddInterceptAPI(@ozDrawTextA, @DrawTextA, @DrawTextAHook, 'DrawTextA'); // AddInterceptAPI(@ozDrawTextW, @DrawTextW, @DrawTextWHook, 'DrawTextW'); end; end; // if aOpt.bPrintMasking then // begin // AddInterceptAPI(@ozStartDocA, @StartDocA, @StartDocAHook, 'StartDocA'); // AddInterceptAPI(@ozStartDocW, @StartDocW, @StartDocWHook, 'StartDocW'); // AddInterceptAPI(@ozEndDoc, @EndDoc, @EndDocHook, 'EndDoc'); // // AddInterceptAPI(@ozExtTextOutA, @ExtTextOutA, @ExtTextOutAHook, 'ExtTextOutA'); // notepad++, WORD등.. 대부분 여기서 처리됨 24_0524 13:23:03 kku // AddInterceptAPI(@ozExtTextOutW, @ExtTextOutW, @ExtTextOutWHook, 'ExtTextOutW'); // notepad++, WORD등.. 대부분 여기서 처리됨 24_0524 13:23:03 kku // // AddInterceptAPI(@ozDrawTextA, @DrawTextA, @DrawTextAHook, 'DrawTextA'); // AddInterceptAPI(@ozDrawTextW, @DrawTextW, @DrawTextWHook, 'DrawTextW'); // AddInterceptAPI(@ozDrawTextExA, @DrawTextExA, @DrawTextExAHook, 'DrawTextExA'); // AddInterceptAPI(@ozDrawTextExW, @DrawTextExW, @DrawTextExWHook, 'DrawTextExW'); // AddInterceptAPI(@ozTextOutA, @TextOutA, @TextOutAHook, 'TextOutA'); // AddInterceptAPI(@ozTextOutW, @TextOutW, @TextOutWHook, 'TextOutW'); // AddInterceptAPI(@ozPolyTextOutA, @PolyTextOutA, @PolyTextOutAHook, 'PolyTextOutA'); // AddInterceptAPI(@ozPolyTextOutW, @PolyTextOutW, @PolyTextOutWHook, 'PolyTextOutW'); // AddInterceptAPI(@ozTabbedTextOutA, @TabbedTextOutA, @TabbedTextOutAHook, 'TabbedTextOutA'); // AddInterceptAPI(@ozTabbedTextOutW, @TabbedTextOutW, @TabbedTextOutWHook, 'TabbedTextOutW'); // end; except // .. end; end; procedure TBS1Hook.ProcessNoti(nNotiCode: Integer; sPath: String; nFType: Integer; bDirect: Boolean = false); var llInfo: LONGLONG; Send: ISendPacket; begin try // if Helper_.CtrlOpt.hRcvWnd = 0 then // exit; if nNotiCode = NOTI_HOOK_OPEN_DRM then begin if DrmFList_.IndexOf(sPath) <> -1 then exit; DrmFList_.Add(sPath); end; case nNotiCode of NOTI_HOOK_MONITOR_ATTACH, NOTI_HOOK_BLOCK_ATTACH : begin // 첨부 파일 차단의 경우 어디서 차단됐는지 정보도 추가해줌 22_1028 14:02:22 kku llInfo := Integer(Helper_.CurAppType); end; else llInfo := 0; end; Send := TTgPacket.Create(ACC_NOTI_MSG); Send.I['Noti'] := nNotiCode; Send.S['MdName'] := ModuleName; Send.I['PID'] := PID; Send.S['FPath'] := sPath; Send.I['FType'] := nFType; // 0 : 없는 파일, 1: 존재 파일, 2 : 네트워크 파일, 3 : 특수 경로 파일 Send.I['Info'] := llInfo; if bDirect and (Helper_.CtrlOpt.hRcvWnd <> 0) then begin SendCopyData(Helper_.CtrlOpt.hRcvWnd, HPCMD_HOOK_NOTI, Send.ToJsonString); end else Client_.SendPacket(Send); except // ... end; end; procedure TBS1Hook.DoInterceptRemove; procedure RemoveAPI(var aProc: Pointer); var nRet: Integer; begin if aProc <> nil then begin nRet := InterceptRemove(aProc); // Log('DoInterceptRemove() .. RemoveAPI() .. nRet=' + IntToStr(nRet)); aProc := nil; end; end; var i: Integer; begin Log('DoInterceptRemove()'); for i := 0 to ProcList_.Count - 1 do RemoveAPI(ProcList_[i]^); ProcList_.Clear; // {$IFDEF USE_BOXAPP} // BoxedAppSDK_Exit; // {$ENDIF} end; procedure TBS1Hook.AddInterceptAPI(var aProcDest: Pointer; aProcSrc, aProcHook: Pointer; sProcName: String); begin if aProcDest = nil then begin aProcDest := InterceptCreate(aProcSrc, aProcHook); if aProcDest <> nil then begin Log(Format('>>> InterceptCreate() - %s <<<', [sProcName])); ProcList_.Add(@aProcDest); end else Log(Format('>>> Fail .. InterceptCreate() - %s <<<', [sProcName])); end; end; procedure TBS1Hook.Log(sLog: String); begin if Trace_ <> nil then begin _bLogProcessing := true; Trace_.T('(%s) %s', [ModuleName, sLog]); _bLogProcessing := false; end; end; procedure TBS1Hook.Log(const sFormat: string; const Args: array of const); var str: String; begin FmtStr(str, sFormat, Args); Log(str); end; procedure TBS1Hook.AddCreateFile(hFile: THandle; sPath: String); begin try // Lock; try if RFileList_.IndexOf(sPath) = -1 then RFileList_.AddObject(sPath, TObject(hFile)); finally // Unlock; end; except // .. end; end; procedure TBS1Hook.DelCloseFile(hFile: THandle); var i: Integer; begin try Lock; try for i := 0 to RFileList_.Count - 1 do if hFile = THandle(RFileList_.Objects[i]) then begin RFileList_.Delete(i); exit; end; finally Unlock; end; except // .. end; end; function TBS1Hook.GetRFilePath(sFName: String): String; var i: Integer; begin Result := ''; try sFName := UpperCase(sFName); Lock; try for i := 0 to RFileList_.Count - 1 do if Pos(UpperCase(ExtractFileName(RFileList_[i])), sFName) > 0 then begin Result := RFileList_[i]; exit; end; finally Unlock; end; except // .. end; end; end.