{*******************************************************} { } { EtcHook } { } { Copyright (C) 2022 kku } { } {*******************************************************} unit EtcHook; interface uses System.SysUtils, System.Classes, Tocsg.DllEntry, Tocsg.CommonData, GlobalDefine, Winapi.Windows, Winapi.Messages, Winapi.ShellAPI, Tocsg.Trace; const IGNORE_PROCESS = '1explorer.exe|taskmgr.exe|dropbox.exe|1kakaotalk.exe|1telegram.exe|' + 'regedit.exe|eCrmHomeEdition.exe|Everything.exe|Listary.exe|' + 'OpenWith.exe|ApplicationFrameHost.exe|conhost.exe'; SMALL_FONT = 'chrome.exe|msedge.exe'; BLOCK_DROP = 'chrome.exe|msedge.exe'; START_PROCESS = 'excel.exe'; WORD_GAP = ' '; CaptureBlt = $40000000; type TPrintHook = class(TKuDllEntry) private SharedData_: TTgFileMapping; Trace_: TTgTrace; dtCreate_: TDateTime; hWndHook_, hMsgHook_, hCbtHook_, hShellHook_: HHook; sPtrText_, sImgPath_, sLogPath_: String; bIsStartPage_, bIsPrinting_, bInitOk_, bBlockDrop_, bStartProc_, bSmallFont_: Boolean; procedure Log(sLog: String); procedure DoInterceptCreate; procedure DoInterceptRemove; function InstallHook: Integer; function UnInstallHook: Integer; public Constructor Create; Destructor Destroy; override; end; TFun_StartDocA = function(dc: HDC; pDocInfo: PDocInfoA): Integer; stdcall; TFun_StartDocW = function(dc: HDC; pDocInfo: PDocInfoW): Integer; stdcall; TFun_HDC = function(dc: HDC): Integer; stdcall; TFun_DragQueryFileA = function(Drop: HDROP; FileIndex: UINT; FileName: LPSTR; cb: UINT): UINT; stdcall; TFun_DragQueryFileW = function(Drop: HDROP; FileIndex: UINT; FileName: LPWSTR; cb: UINT): UINT; stdcall; TFun_DrawTextA = function(hDC: HDC; lpString: LPCSTR; nCount: Integer; var lpRect: TRect; uFormat: UINT): Integer; stdcall; TFun_DrawTextW = function(hDC: HDC; lpString: LPCWSTR; nCount: Integer; var lpRect: TRect; uFormat: UINT): Integer; stdcall; TFun_DrawTextExA = function(DC: HDC; lpchText: LPCSTR; cchText: Integer; var p4: TRect; dwDTFormat: UINT; DTParams: PDrawTextParams): Integer; stdcall; TFun_DrawTextExW = function(DC: HDC; lpchText: LPCWSTR; cchText: Integer; var p4: TRect; dwDTFormat: UINT; DTParams: PDrawTextParams): Integer; stdcall; TFun_ExtTextOutA = function(DC: HDC; X, Y: Integer; Options: Longint; Rect: PRect; Str: LPCSTR; Count: Longint; Dx: PInteger): BOOL; stdcall; TFun_ExtTextOutW = function(DC: HDC; X, Y: Integer; Options: Longint; Rect: PRect; Str: LPCWSTR; Count: Longint; Dx: PInteger): BOOL; stdcall; TFun_TextOutA = function(DC: HDC; X, Y: Integer; Str: LPCSTR; Count: Integer): BOOL; stdcall; TFun_TextOutW = function(DC: HDC; X, Y: Integer; Str: LPCWSTR; Count: Integer): BOOL; stdcall; TFun_PolyTextOutA = function(DC: HDC; const PolyTextArray; Strings: Integer): BOOL; stdcall; TFun_PolyTextOutW = function(DC: HDC; const PolyTextArray; Strings: Integer): BOOL; stdcall; function InstallPrintHook: Integer; export; stdcall; function UninstallPrintHook: Integer; export; stdcall; implementation uses DDetours, Vcl.Graphics, Vcl.Imaging.pngimage, Vcl.Imaging.jpeg, Tocsg.Safe, Tocsg.Path, Tocsg.Strings; var _PrintHook: TPrintHook = nil; _bLogProcessing: Boolean = false; ozStartDocA: TFun_StartDocA = nil; ozStartDocW: TFun_StartDocW = nil; ozStartPage: TFun_HDC = nil; ozBeginPath: TFun_HDC = nil; ozFillPath: TFun_HDC = nil; ozEndPage: TFun_HDC = nil; ozEndDoc: TFun_HDC = nil; ozDragQueryFileA: TFun_DragQueryFileA = nil; ozDragQueryFileW: TFun_DragQueryFileW = nil; ozDrawTextA: TFun_DrawTextA = nil; ozDrawTextW: TFun_DrawTextW = nil; ozDrawTextExA: TFun_DrawTextExA = nil; ozDrawTextExW: TFun_DrawTextExW = nil; ozExtTextOutA: TFun_ExtTextOutA = nil; ozExtTextOutW: TFun_ExtTextOutW = nil; ozTextOutA: TFun_TextOutA = nil; ozTextOutW: TFun_TextOutW = nil; ozPolyTextOutA: TFun_PolyTextOutA = nil; ozPolyTextOutW: TFun_PolyTextOutW = nil; function process_WH_CALLWNDPROC(nCode: Integer; wParam: WPARAM; lParam: LPARAM): LRESULT; stdcall; var cwp: PCWPStruct; begin if Assigned(_PrintHook) then Result := CallNextHookEx(_PrintHook.hWndHook_, nCode, wParam, lParam) else Result := 0; end; function process_WH_GETMESSAGE(nCode: Integer; wParam: WPARAM; lParam: LPARAM): LRESULT; stdcall; begin if Assigned(_PrintHook) then Result := CallNextHookEx(_PrintHook.hMsgHook_, nCode, wParam, lParam) else Result := 0; end; function process_WH_CBT(nCode: Integer; wParam: WPARAM; lParam: LPARAM): LRESULT; stdcall; begin if Assigned(_PrintHook) then begin try try if nCode >= HC_ACTION then case nCode of HCBT_CREATEWND : ; // À©µµ¿ì°¡ »ý¼ºµÈ °æ¿ì´Ù, WM_CREATE, WM_NCCREATE ÇÁ·Î½ÃÀú°¡ ¾ÆÁ÷ ¼öÇàµÇÁö ¾ÊÀº ´Ü°è HCBT_DESTROYWND : ; // À©µµ¿ì°¡ ÆÄ±«µÈ °æ¿ì´Ù HCBT_ACTIVATE : ; // À©µµ¿ì°¡ Ȱ¼ºÈ­ µÈ °æ¿ì´Ù HCBT_CLICKSKIPPED : ; // ¸¶¿ì½º ¸Þ½ÃÁö°¡ ½Ã½ºÅÛ ¸Þ½ÃÁö¿¡¼­ Á¦°ÅµÈ °æ¿ì´Ù HCBT_KEYSKIPPED : ; // Űº¸µå ¸Þ½ÃÁö°¡ ½Ã½ºÅÛ ¸Þ½ÃÁö Å¥¿¡¼­ Á¦°ÅµÈ °æ¿ì´Ù HCBT_MINMAX : ; // À©µµ¿ì°¡ ÃÖ¼ÒÈ­/ÃÖ´ëÈ­°¡ µÈ °æ¿ì´Ù HCBT_MOVESIZE : ; // À©µµ¿ì°¡ ¿Å°ÜÁö°Å³ª Å©±â°¡ º¯°æµÈ °æ¿ì´Ù HCBT_QS : ; // ½Ã½ºÅÛ ¸Þ½ÃÁö Å¥·ÎºÎÅÍ WM_QUEUESYNC ¸Þ½ÃÁö¸¦ Àü´Þ¹ÞÀº °æ¿ì´Ù HCBT_SETFOCUS : ; // À©µµ¿ì°¡ Űº¸µå Æ÷Ä¿½º¸¦ °¡Áö°Ô µÈ °æ¿ì´Ù HCBT_SYSCOMMAND : ; // ½Ã½ºÅÛ ¸í·É(WM_SYSCOMMAND)ÀÌ ¼öÇàµÇ´Â °æ¿ì´Ù end; except exit; end; finally Result := CallNextHookEx(_PrintHook.hCbtHook_, nCode, wParam, lParam); end; end else Result := 0;//CallNextHookEx(0, nCode, wParam, lParam); end; function process_WH_SHELL(nCode: Integer; wParam: WPARAM; lParam: LPARAM): LRESULT; stdcall; var i: Integer; sTitle: String; begin if Assigned(_PrintHook) then begin try try if nCode >= HC_ACTION then case nCode of // HSHELL_ACCESSIBILITYSTATE : _PrintHook.Log('HSHELL_ACCESSIBILITYSTATE'); // Windows 2000/XP: accessibility »óŰ¡ º¯°æµÇ¾úÀ½ // HSHELL_APPCOMMAND : _PrintHook.Log('HSHELL_APPCOMMAND'); // Windows 2000/XP: »ç¿ëÀÚÀÇ ÀÔ·Â À̺¥Æ®¿¡ ÀÇÇØ¼­ WM_APPCOMMAND °¡ ¹ß»ýÇÑ °æ¿ì´Ù // HSHELL_ACTIVATESHELLWINDOW : _PrintHook.Log('HSHELL_ACTIVATESHELLWINDOW'); // ½© ¸ÞÀÎ À©µµ¿ì°¡ Ȱ¼ºÈ­ µÇ¾î¾ß ÇÏ´Â °æ¿ì´Ù // HSHELL_GETMINRECT : _PrintHook.Log('HSHELL_GETMINRECT'); // À©µµ¿ì°¡ ÃÖ¼ÒÈ­/ÃÖ´ëÈ­µÈ °æ¿ì´Ù // HSHELL_LANGUAGE : _PrintHook.Log('HSHELL_LANGUAGE'); // Űº¸µå ¾ð¾î°¡ º¯°æµÇ°Å³ª »õ·Î¿î Űº¸µå ·¹À̾ƿôÀÌ ·ÎµåµÈ °æ¿ì´Ù HSHELL_REDRAW : ; // ŽºÅ©¹Ù¿¡ ÀÖ´Â À©µµ¿ì ŸÀÌÆ²ÀÌ »õ·Î ±×·ÁÁö´Â °æ¿ì´Ù HSHELL_WINDOWACTIVATED : ; // ž ·¹º§ À©µµ¿ìÀÇ È°¼ºÈ­ »óŰ¡ º¯°æµÈ °æ¿ì´Ù HSHELL_WINDOWCREATED : ; // ž ·¹º§ À©µµ¿ì°¡ »ý¼ºµÈ °æ¿ì´Ù. ÀÌ ÈÅÀÌ È£ÃâµÇ´Â ½ÃÁ¡¿¡ À©µµ¿ì´Â »ý¼ºµÈ »óÅ´٠HSHELL_WINDOWDESTROYED : ; // ž ·¹º§ À©µµ¿ì°¡ ÆÄ±«µÈ °æ¿ì´Ù. ÀÌ ÈÅÀÌ È£ÃâµÇ´Â ½ÃÁ¡¿¡ À©µµ¿ì´Â Á¸ÀçÇÑ´Ù HSHELL_WINDOWREPLACED : ;//_PrintHook.Log('HSHELL_WINDOWREPLACED'); // Windows XP: ž ·¹º§ À©µµ¿ì°¡ ´ëü(replaced)µÈ °æ¿ì´Ù end; except exit; end; finally Result := CallNextHookEx(_PrintHook.hShellHook_, nCode, wParam, lParam); end; end else Result := 0; end; function StartDocAHook(dc: HDC; pDocInfo: PDocInfoA): Integer; stdcall; begin _PrintHook.Log('StartDocAHook() - lpszDocName = ' + AnsiString(pDocInfo.lpszDocName)); // _PrintHook.Log('StartDocAHook() - lpszOutput = ' + AnsiString(pDocInfo.lpszOutput)); // _PrintHook.Log('StartDocAHook() - lpszDatatype = ' + AnsiString(pDocInfo.lpszDatatype)); _PrintHook.sPtrText_ := ''; _PrintHook.bIsPrinting_ := true; if FileExists(_PrintHook.sLogPath_) then DeleteFile(PChar(ExtractFilePath(_PrintHook.sLogPath_) + 'PrintText.txt')); Result := ozStartDocA(dc, pDocInfo); end; function StartDocWHook(dc: HDC; pDocInfo: PDocInfoW): Integer; stdcall; begin _PrintHook.Log('StartDocWHook() - lpszDocName = ' + String(pDocInfo.lpszDocName)); // _PrintHook.Log('StartDocWHook() - lpszOutput = ' + String(pDocInfo.lpszOutput)); // _PrintHook.Log('StartDocWHook() - lpszDatatype = ' + String(pDocInfo.lpszDatatype)); _PrintHook.sPtrText_ := ''; _PrintHook.bIsPrinting_ := true; if FileExists(_PrintHook.sLogPath_) then DeleteFile(PChar(ExtractFilePath(_PrintHook.sLogPath_) + 'PrintText.txt')); Result := ozStartDocW(dc, pDocInfo); end; function ProcessWartermark(DC: HDC): Boolean; var nW, nH, nX, i, nGapH, nRepeat: Integer; sExt, sOut, sImgPath: String; cc: TCanvas; hbmp: HBITMAP; bf: BLENDFUNCTION; bmp: TBitmap; bImgLoad: Boolean; pen: HPEN; begin Result := false; try nW := GetDeviceCaps(DC, HORZRES); nH := GetDeviceCaps(DC, VERTRES); Guard(cc, TCanvas.Create); cc.Handle := CreateCompatibleDC(DC); hbmp := CreateCompatibleBitmap(DC, nW, nH); SelectObject(cc.Handle, hbmp); _PrintHook.Log(Format('ProcessWartermark() - DocSize W=%d, H=%d, dc=%d, cdc=%d', [nW, nH, DC, cc.Handle])); bImgLoad := false; Guard(bmp, TBitmap.Create); sImgPath := _PrintHook.SharedData_.Data.sImgPath; if FileExists(sImgPath) then begin try sOut := GetFileExt(sImgPath).ToUpper; if sOut = 'PNG' then begin var png: TPngImage; Guard(png, TPngImage.Create); png.LoadFromFile(sImgPath); bmp.Assign(png); end else if (sOut = 'JPG') or (sOut = 'JPEG') then begin var jpg: TJPEGImage; Guard(jpg, TJPEGImage.Create); jpg.LoadFromFile(sImgPath); bmp.Assign(jpg); end else if sOut = 'bmp' then bmp.LoadFromFile(sImgPath); // BitBlt(cc.Handle, (nW div 2) - (bmp.Width div 2), // (nH div 2) - (bmp.Height div 2), // bmp.Width, bmp.Height, bmp.Canvas.Handle, 0, 0, SRCCOPY); if not StretchBlt(cc.Handle, 0, 0, nW, nH, bmp.Canvas.Handle, 0, 0, bmp.Width, bmp.Height, SRCCOPY) then _PrintHook.Log('ProcessWartermark() - Fail .. StretchBlt() .. 1'); // StretchBlt(cc.Handle, (nW div 2) - 400, (nH div 2) - 300, nW div 2, nH div 2, bmp.Canvas.Handle, 0, 0, bmp.Width, bmp.Height, SRCCOPY); bImgLoad := true; except // ... end; end; if not bImgLoad then begin // À̹ÌÁö ¾øÀ»¶§ ÀÌ·¸°Ô ¾ÈÇϸé... ¹è°æÀÌ °Å¹«Æ¢Æ¼ ÇØÁø´Ù.. // ÇöÀç ÇØ°á ¹æ¹ýÀ» ¸ô¶ó¼­ ÀÌ·¸°Ô ó¸® ÇÔ 22_0907 10:51:58 kku bmp.Width := nW; bmp.Height := nH; if not StretchBlt(cc.Handle, 0, 0, nW, nH, bmp.Canvas.Handle, 0, 0, bmp.Width, bmp.Height, SRCCOPY) then _PrintHook.Log('ProcessWartermark() - Fail .. StretchBlt() .. 2'); end; pen := CreatePen(PS_SOLID, 4, RGB(255, 0, 0)); SelectObject(cc.Handle, pen); sOut := _PrintHook.SharedData_.Data.sText; // 'À̰ÍÀº Å×½ºÆ® ÀÔ´Ï´Ù. ±¸Áø±¸Áø'; SetBkMode(cc.Handle, TRANSPARENT); if _PrintHook.bSmallFont_ then begin cc.Font.Size := _PrintHook.SharedData_.Data.nFontSize - 125; if cc.Font.Size < 10 then cc.Font.Size := 10; end else cc.Font.Size := _PrintHook.SharedData_.Data.nFontSize; cc.Font.Color := clGray; cc.Font.Style := cc.Font.Style + [fsBold]; cc.Font.Orientation := 250; _PrintHook.Log(Format('ProcessWartermark() - Font.Size=%d', [cc.Font.Size])); nX := 0; for i := 0 to 3 do sOut := sOut + WORD_GAP + sOut; i := 0; nRepeat := _PrintHook.SharedData_.Data.nLineCnt; nGapH := nH div (nRepeat - 1); while i < nH + nGapH do begin cc.TextOut(nX, i, sOut); Inc(i, nGapH); // Dec(nX, 50); end; bf.AlphaFormat := 0; // ÀÏ¹Ý ºñÆ®¸Ê 0, 32ºñÆ® ºñÆ®¸Ê AC_SRC_ALPHA bf.BlendFlags := 0; // ¹«Á¶°Ç 0 bf.BlendOp := AC_SRC_OVER; // AC_SRC_OVER bf.SourceConstantAlpha := 50; // Åõ¸íµµ(Åõ¸í 0 - ºÒÅõ¸í 255) if not AlphaBlend(DC, 0, 0, nW, nH, cc.Handle, 0, 0, nW, nH, bf) then _PrintHook.Log('ProcessWartermark() - Fail .. AlphaBlend()'); DeleteObject(pen); DeleteObject(hbmp); DeleteDC(cc.Handle); cc.Handle := 0; _PrintHook.Log(Format('ProcessWartermark() - Completed, LastError=%d', [GetLastError])); Result := true; except // ½ÇÆÐÇϸé Ãâ·Â ¾ÈµÇ°Ô ÇØÁØ´Ù 22_0907 14:28:52 kku Result := false; DeleteDC(DC); end; end; function StartPageHook(dc: HDC): Integer; stdcall; begin _PrintHook.bIsStartPage_ := true; Result := ozStartPage(dc); _PrintHook.Log('StartPageHook()'); // º°µµ ÇÁ·Î½ÃÀú ¸¸µé¾î¼­ »ç¿ëÇÏ¸é ¾ÈµÈ´Ù.. ±×·¡¼­ StartPageHook(), EndPageHook() °¢°¢ ±¸Çö 22_0907 15:06:14 kku if not _PrintHook.SharedData_.Data.bActive or not _PrintHook.bStartProc_ then exit; if Result = 1 then begin if not ProcessWartermark(dc) then Result := -1; end; end; function BeginPathHook(dc: HDC): Integer; stdcall; begin // Result := 1; // exit; Result := ozBeginPath(dc); _PrintHook.Log('BeginPathHook()'); end; function FillPathHook(dc: HDC): Integer; stdcall; begin // Result := 1; // exit; Result := ozFillPath(dc); _PrintHook.Log('FillPathHook()'); // if _PrintHook.bSmallFont_ and not _PrintHook.bIsStartPage_ then // begin // if not ProcessWartermark(dc) then // Result := -1; // end; end; function EndPageHook(dc: HDC): Integer; stdcall; begin if _PrintHook.SharedData_.Data.bActive and not _PrintHook.bStartProc_ then begin if not ProcessWartermark(dc) then begin Result := -1; exit; end; end; _PrintHook.Log('EndPageHook()'); _PrintHook.bIsStartPage_ := false; Result := ozEndPage(dc); end; function EndDocHook(dc: HDC): Integer; stdcall; begin _PrintHook.bIsPrinting_ := false; if FileExists(_PrintHook.sLogPath_) then WriteLnFileEndUTF8(ExtractFilePath(_PrintHook.sLogPath_) + 'PrintText.txt', _PrintHook.sPtrText_); Result := ozEndDoc(dc); _PrintHook.Log('EndDocHook()'); end; function DragQueryFileAHook(Drop: HDROP; FileIndex: UINT; FileName: LPSTR; cb: UINT): UINT; stdcall; begin if _PrintHook.SharedData_.Data.bActive then begin // Â÷´Ü Result := 0; end else Result := ozDragQueryFileA(Drop, FileIndex, FileName, cb); end; function DragQueryFileWHook(Drop: HDROP; FileIndex: UINT; FileName: LPWSTR; cb: UINT): UINT; stdcall; begin if _PrintHook.SharedData_.Data.bActive then begin // Â÷´Ü Result := 0; end else Result := ozDragQueryFileW(Drop, FileIndex, FileName, cb); end; procedure ReplaceTextA(sStr: LPCSTR); inline; stdcall; var sData: AnsiString; bMod: Boolean; begin bMod := false; sData := AnsiString(sStr); if Pos('±è±¸Áø', sData) > 0 then begin sData := StringReplace(sData, '±è±¸Áø', '±èÁ¾¹«', [rfReplaceAll]); bMod := true; end; if Pos('±èÁø¾Æ', sData) > 0 then begin sData := StringReplace(sData, '±èÁø¾Æ', '±èÁ¾¹«', [rfReplaceAll]); bMod := true; end; if Pos('¼³ÀçÈ£', sData) > 0 then begin sData := StringReplace(sData, '¼³ÀçÈ£', '±èÁ¾¹«', [rfReplaceAll]); bMod := true; end; if Pos('Á¶ÇöÈ£', sData) > 0 then begin sData := StringReplace(sData, 'Á¶ÇöÈ£', '±èÁ¾¹«', [rfReplaceAll]); bMod := true; end; if Pos('±è°æ´ö', sData) > 0 then begin sData := StringReplace(sData, '±è°æ´ö', '±èÁ¾¹«', [rfReplaceAll]); bMod := true; end; if Pos('±æÁ¤¿ì', sData) > 0 then begin sData := StringReplace(sData, '±æÁ¤¿ì', '±èÁ¾¹«', [rfReplaceAll]); bMod := true; end; if Pos('Á¤¿ì¼º', sData) > 0 then begin sData := StringReplace(sData, 'Á¤¿ì¼º', '±èÁ¾¹«', [rfReplaceAll]); bMod := true; end; if Pos('svchost', sData) > 0 then begin sData := StringReplace(sData, 'svchost', 'xxxxxxx', [rfReplaceAll]); bMod := true; end; if bMod then CopyMemory(@sStr[0], @sData[1], Length(sData)); end; procedure ReplaceTextW(sStr: LPCWSTR); inline; stdcall; var sData: String; bMod: Boolean; begin bMod := false; sData := String(sStr); if Pos('±è±¸Áø', sData) > 0 then begin sData := StringReplace(sData, '±è±¸Áø', '±èÁ¾¹«', [rfReplaceAll]); bMod := true; end; if Pos('±èÁø¾Æ', sData) > 0 then begin sData := StringReplace(sData, '±èÁø¾Æ', '±èÁ¾¹«', [rfReplaceAll]); bMod := true; end; if Pos('¼³ÀçÈ£', sData) > 0 then begin sData := StringReplace(sData, '¼³ÀçÈ£', '±èÁ¾¹«', [rfReplaceAll]); bMod := true; end; if Pos('Á¶ÇöÈ£', sData) > 0 then begin sData := StringReplace(sData, 'Á¶ÇöÈ£', '±èÁ¾¹«', [rfReplaceAll]); bMod := true; end; if Pos('±è°æ´ö', sData) > 0 then begin sData := StringReplace(sData, '±è°æ´ö', '±èÁ¾¹«', [rfReplaceAll]); bMod := true; end; if Pos('±æÁ¤¿ì', sData) > 0 then begin sData := StringReplace(sData, '±æÁ¤¿ì', '±èÁ¾¹«', [rfReplaceAll]); bMod := true; end; if Pos('Á¤¿ì¼º', sData) > 0 then begin sData := StringReplace(sData, 'Á¤¿ì¼º', '±èÁ¾¹«', [rfReplaceAll]); bMod := true; end; if Pos('svchost', sData) > 0 then begin sData := StringReplace(sData, 'svchost', 'xxxxxxx', [rfReplaceAll]); bMod := true; end; if bMod then CopyMemory(@sStr[0], @sData[1], Length(sData) * 2); end; function DrawTextAHook(hDC: HDC; lpString: LPCSTR; nCount: Integer; var lpRect: TRect; uFormat: UINT): Integer; stdcall; var sData: AnsiString; begin if _PrintHook.SharedData_.Data.bActive and _PrintHook.bIsPrinting_ then begin ReplaceTextA(lpString); sData := AnsiString(lpString); SumString(_PrintHook.sPtrText_, sData, ' '); end; Result := ozDrawTextA(hDc, lpString, nCount, lpRect, uFormat); end; function DrawTextWHook(hDC: HDC; lpString: LPCWSTR; nCount: Integer; var lpRect: TRect; uFormat: UINT): Integer; stdcall; var sData: String; begin if _PrintHook.SharedData_.Data.bActive and _PrintHook.bIsPrinting_ then begin ReplaceTextW(lpString); sData := String(lpString); SumString(_PrintHook.sPtrText_, sData, ' '); end; Result := ozDrawTextW(hDc, lpString, nCount, lpRect, uFormat); end; function DrawTextExAHook(DC: HDC; lpchText: LPCSTR; cchText: Integer; var p4: TRect; dwDTFormat: UINT; DTParams: PDrawTextParams): Integer; stdcall; var sData: AnsiString; begin if _PrintHook.SharedData_.Data.bActive and _PrintHook.bIsPrinting_ then begin ReplaceTextA(lpchText); sData := AnsiString(lpchText); SumString(_PrintHook.sPtrText_, sData, ' '); end; Result := ozDrawTextExA(DC, lpchText, cchText, p4, dwDTFormat, DTParams); end; function DrawTextExWHook(DC: HDC; lpchText: LPCWSTR; cchText: Integer; var p4: TRect; dwDTFormat: UINT; DTParams: PDrawTextParams): Integer; stdcall; var sData: String; begin if _PrintHook.SharedData_.Data.bActive and _PrintHook.bIsPrinting_ then begin ReplaceTextW(lpchText); sData := String(lpchText); SumString(_PrintHook.sPtrText_, sData, ' '); end; Result := ozDrawTextExW(DC, lpchText, cchText, p4, dwDTFormat, DTParams); end; function ExtTextOutAHook(DC: HDC; X, Y: Integer; Options: Longint; Rect: PRect; Str: LPCSTR; Count: Longint; Dx: PInteger): BOOL; stdcall; var sData: AnsiString; begin if _PrintHook.SharedData_.Data.bActive and _PrintHook.bIsPrinting_ then begin ReplaceTextA(Str); sData := AnsiString(Str); SumString(_PrintHook.sPtrText_, sData, ' '); end; Result := ozExtTextOutA(DC, X, Y, Options, Rect, Str, Count, Dx); end; function ExtTextOutWHook(DC: HDC; X, Y: Integer; Options: Longint; Rect: PRect; Str: LPCWSTR; Count: Longint; Dx: PInteger): BOOL; stdcall; var sData: String; begin if _PrintHook.SharedData_.Data.bActive and _PrintHook.bIsPrinting_ then begin ReplaceTextW(Str); sData := String(Str); SumString(_PrintHook.sPtrText_, String(Str), ' '); end; Result := ozExtTextOutW(DC, X, Y, Options, Rect, Str, Count, Dx); end; function TextOutAHook(DC: HDC; X, Y: Integer; Str: LPCSTR; Count: Integer): BOOL; stdcall; var sData: AnsiString; begin if _PrintHook.SharedData_.Data.bActive and _PrintHook.bIsPrinting_ then begin ReplaceTextA(Str); sData := AnsiString(Str); SumString(_PrintHook.sPtrText_, sData, ' '); end; Result := ozTextOutA(DC, X, Y, Str, Count); end; function TextOutWHook(DC: HDC; X, Y: Integer; Str: LPCWSTR; Count: Integer): BOOL; stdcall; var sData: String; begin if _PrintHook.SharedData_.Data.bActive and _PrintHook.bIsPrinting_ then begin ReplaceTextW(Str); sData := String(Str); SumString(_PrintHook.sPtrText_, sData, ' '); end; Result := ozTextOutW(DC, X, Y, Str, Count); end; function PolyTextOutAHook(DC: HDC; const PolyTextArray; Strings: Integer): BOOL; stdcall; type TArrayLPCSTR = array [0..0] of LPCSTR; var i: Integer; begin if _PrintHook.SharedData_.Data.bActive and _PrintHook.bIsPrinting_ then begin try for i := 0 to Strings - 1 do begin ReplaceTextA(TArrayLPCSTR(PolyTextArray)[i]); SumString(_PrintHook.sPtrText_, AnsiString(TArrayLPCSTR(PolyTextArray)[i]), ' '); end; except // .. end; end; Result := ozPolyTextOutA(DC, PolyTextArray, Strings); end; function PolyTextOutWHook(DC: HDC; const PolyTextArray; Strings: Integer): BOOL; stdcall; type TArrayLPCWSTR = array [0..0] of LPCWSTR; var i: Integer; begin if _PrintHook.SharedData_.Data.bActive and _PrintHook.bIsPrinting_ then begin try for i := 0 to Strings - 1 do begin ReplaceTextW(TArrayLPCWSTR(PolyTextArray)[i]); SumString(_PrintHook.sPtrText_, String(TArrayLPCWSTR(PolyTextArray)[i]), ' '); end; except // .. end; end; Result := ozPolyTextOutW(DC, PolyTextArray, Strings); end; { TPrintHook } Constructor TPrintHook.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; begin Inherited Create; ASSERT(_PrintHook = nil); _PrintHook := Self; hWndHook_ := 0; hMsgHook_ := 0; hShellHook_ := 0; bInitOk_ := false; bIsPrinting_ := true; bIsStartPage_ := false; sPtrText_ := ''; GetStartTime; SharedData_ := TTgFileMapping.Create(MAP_FILENAME_APIHOOK, SizeOf(TSharedData)); if SharedData_.IsAvailable then begin sImgPath_ := SharedData_.Data.sImgPath; sLogPath_ := SharedData_.Data.sLogPath; end; Guard(IgrList, TStringList.Create); IgrList.CaseSensitive := false; SplitString(START_PROCESS, '|', IgrList); bStartProc_ := IgrList.IndexOf(ModuleName) > -1; SplitString(SMALL_FONT, '|', IgrList); bSmallFont_ := IgrList.IndexOf(ModuleName) > -1; SplitString(BLOCK_DROP, '|', IgrList); bBlockDrop_ := IgrList.IndexOf(ModuleName) > -1; SplitString(IGNORE_PROCESS, '|', IgrList); if IgrList.IndexOf(ModuleName) = -1 then begin Trace_ := TTgTrace.Create(ExtractFilePath(sLogPath_), ExtractFileName(sLogPath_)); DoInterceptCreate; end; end; Destructor TPrintHook.Destroy; begin _PrintHook := nil; UnInstallHook; if Trace_ <> nil then FreeAndNil(Trace_); Inherited; end; procedure TPrintHook.DoInterceptCreate; begin Log('DoInterceptCreate()'); DoInterceptRemove; if @ozStartDocA = nil then begin ozStartDocA := InterceptCreate(@StartDocA, @StartDocAHook); Log('>>> InterceptCreate() - StartDocA <<<'); end; if @ozStartDocW = nil then begin ozStartDocW := InterceptCreate(@StartDocW, @StartDocWHook); Log('>>> InterceptCreate() - StartDocW <<<'); end; if @ozStartPage = nil then begin ozStartPage := InterceptCreate(@StartPage, @StartPageHook); Log('>>> InterceptCreate() - StartPage <<<'); end; if @ozBeginPath = nil then begin ozBeginPath := InterceptCreate(@BeginPath, @BeginPathHook); Log('>>> InterceptCreate() - BeginPath <<<'); end; if @ozFillPath = nil then begin ozFillPath := InterceptCreate(@FillPath, @FillPathHook); Log('>>> InterceptCreate() - BeginPath <<<'); end; if @ozEndPage = nil then begin ozEndPage := InterceptCreate(@EndPage, @EndPageHook); Log('>>> InterceptCreate() - EndPage <<<'); end; if @ozEndDoc = nil then begin ozEndDoc := InterceptCreate(@EndDoc, @EndDocHook); Log('>>> InterceptCreate() - EndDoc <<<'); end; if bBlockDrop_ then begin if @ozDragQueryFileA = nil then begin ozDragQueryFileA := InterceptCreate(@DragQueryFileA, @DragQueryFileAHook); Log('>>> InterceptCreate() - DragQueryFileA <<<'); end; if @ozDragQueryFileW = nil then begin ozDragQueryFileW := InterceptCreate(@DragQueryFileW, @DragQueryFileWHook); Log('>>> InterceptCreate() - DragQueryFileW <<<'); end; end; {$IFDEF DEBUG} if @ozDrawTextA = nil then begin ozDrawTextA := InterceptCreate(@DrawTextA, @DrawTextAHook); Log('>>> InterceptCreate() - DrawTextA <<<'); end; if @ozDrawTextW = nil then begin ozDrawTextW := InterceptCreate(@DrawTextW, @DrawTextWHook); Log('>>> InterceptCreate() - DrawTextW <<<'); end; if @ozDrawTextExA = nil then begin ozDrawTextExA := InterceptCreate(@DrawTextExA, @DrawTextExAHook); Log('>>> InterceptCreate() - DrawTextExA <<<'); end; if @ozDrawTextExW = nil then begin ozDrawTextExW := InterceptCreate(@DrawTextExW, @DrawTextExWHook); Log('>>> InterceptCreate() - DrawTextExW <<<'); end; if @ozExtTextOutA = nil then begin ozExtTextOutA := InterceptCreate(@ExtTextOutA, @ExtTextOutAHook); Log('>>> InterceptCreate() - ExtTextOutA <<<'); end; if @ozExtTextOutW = nil then begin ozExtTextOutW := InterceptCreate(@ExtTextOutW, @ExtTextOutWHook); Log('>>> InterceptCreate() - ExtTextOutW <<<'); end; if @ozTextOutA = nil then begin ozTextOutA := InterceptCreate(@TextOutA, @TextOutAHook); Log('>>> InterceptCreate() - TextOutA <<<'); end; if @ozTextOutW = nil then begin ozTextOutW := InterceptCreate(@TextOutW, @TextOutWHook); Log('>>> InterceptCreate() - TextOutW <<<'); end; if @ozPolyTextOutA = nil then begin ozPolyTextOutA := InterceptCreate(@PolyTextOutA, @PolyTextOutAHook); Log('>>> InterceptCreate() - PolyTextOutA <<<'); end; if @ozPolyTextOutW = nil then begin ozPolyTextOutW := InterceptCreate(@PolyTextOutW, @PolyTextOutWHook); Log('>>> InterceptCreate() - PolyTextOutW <<<'); end; {$ENDIF} bInitOk_ := true; end; procedure TPrintHook.DoInterceptRemove; begin if bInitOk_ then begin Log('DoInterceptRemove()'); if @ozStartDocA <> nil then begin InterceptRemove(@ozStartDocA); @ozStartDocA := nil; end; if @ozStartDocW <> nil then begin InterceptRemove(@ozStartDocW); @ozStartDocW := nil; end; if @ozStartPage <> nil then begin InterceptRemove(@ozStartPage); @ozStartPage := nil; end; if @ozBeginPath <> nil then begin InterceptRemove(@ozBeginPath); @ozBeginPath := nil; end; if @ozEndPage <> nil then begin InterceptRemove(@ozEndPage); @ozEndPage := nil; end; if @ozEndDoc <> nil then begin InterceptRemove(@ozEndDoc); @ozEndDoc := nil; end; if @ozDragQueryFileA <> nil then begin InterceptRemove(@ozDragQueryFileA); @ozDragQueryFileA := nil; end; if @ozDragQueryFileW <> nil then begin InterceptRemove(@ozDragQueryFileW); @ozDragQueryFileW := nil; end; if @ozDrawTextA <> nil then begin InterceptRemove(@ozDrawTextA); @ozDrawTextA := nil; end; if @ozDrawTextW <> nil then begin InterceptRemove(@ozDrawTextW); @ozDrawTextW := nil; end; if @ozDrawTextExA <> nil then begin InterceptRemove(@ozDrawTextExA); @ozDrawTextExA := nil; end; if @ozDrawTextExW <> nil then begin InterceptRemove(@ozDrawTextExW); @ozDrawTextExW := nil; end; if @ozExtTextOutA <> nil then begin InterceptRemove(@ozExtTextOutA); @ozExtTextOutA := nil; end; if @ozExtTextOutW <> nil then begin InterceptRemove(@ozExtTextOutW); @ozExtTextOutW := nil; end; if @ozTextOutA <> nil then begin InterceptRemove(@ozTextOutA); @ozTextOutA := nil; end; if @ozTextOutW <> nil then begin InterceptRemove(@ozTextOutW); @ozTextOutW := nil; end; if @ozPolyTextOutA <> nil then begin InterceptRemove(@ozPolyTextOutA); @ozPolyTextOutA := nil; end; if @ozPolyTextOutW <> nil then begin InterceptRemove(@ozPolyTextOutW); @ozPolyTextOutW := nil; end; bInitOk_ := false; end; end; procedure TPrintHook.Log(sLog: String); begin if Trace_ <> nil then begin _bLogProcessing := true; Trace_.T('(%s) %s', [ModuleName, sLog]); _bLogProcessing := false; end; end; function TPrintHook.InstallHook: Integer; begin Log('InstallPrintHook'); try // hWndHook_ := SetWindowsHookEx(WH_CALLWNDPROC, process_WH_CALLWNDPROC, HInstance, 0); // if hWndHook_ = 0 then // begin // Log('SetWindowsHookEx(WH_CALLWNDPROC) fail!!'); // Result := 4; // exit; // end; // hMsgHook_ := SetWindowsHookEx(WH_GETMESSAGE, process_WH_GETMESSAGE, HInstance, 0); // if hMsgHook_ = 0 then // begin // Log('SetWindowsHookEx(WH_GETMESSAGE) fail!!'); // Result := 3; // exit; // end; // hCbtHook_ := SetWindowsHookEx(WH_CBT, process_WH_CBT, HInstance, 0); // if hCbtHook_ = 0 then // begin // Log('SetWindowsHookEx(WH_CBT) fail!!'); // Result := 1; // exit; // end; hShellHook_ := SetWindowsHookEx(WH_SHELL, process_WH_SHELL, HInstance, 0); if hShellHook_ = 0 then begin Log('SetWindowsHookEx(WH_SHELL) fail!!'); Result := 2; exit; end; except exit; end; // if (hCbtHook_ <> 0) and (hShellHook_ <> 0) then Result := 0; // else // Result := -2; end; function TPrintHook.UnInstallHook: Integer; begin Log('UninstallPrintHook'); DoInterceptRemove; try if hWndHook_ <> 0 then begin Log('UnhookWindowsHookEx(WndHook)'); UnhookWindowsHookEx(hWndHook_); hWndHook_ := 0; end; if hMsgHook_ <> 0 then begin Log('UnhookWindowsHookEx(MsgHook)'); UnhookWindowsHookEx(hMsgHook_); hMsgHook_ := 0; end; try if hCbtHook_ <> 0 then begin Log('UnhookWindowsHookEx(CbtHook)'); UnhookWindowsHookEx(hCbtHook_); hCbtHook_ := 0; end; except // ¿ÖÀÎÁö.. OS ¸¶´Ù´Ù¸¥°ÇÁö ¸ð¸£°ÚÁö¸¸, ¿À·ù¸¦ ¹ß»ýÇØ¼­ °ü·Ã ÇÁ·Î±×·¥ÀÌ Á״´Ù. 14_1023 17:57:08 sunk hCbtHook_ := 0; end; if hShellHook_ <> 0 then begin Log('UnhookWindowsHookEx(ShellHook)'); UnhookWindowsHookEx(hShellHook_); hShellHook_ := 0; end; except // ¿ÖÀÎÁö.. OS ¸¶´Ù´Ù¸¥°ÇÁö ¸ð¸£°ÚÁö¸¸, ¿À·ù¸¦ ¹ß»ýÇØ¼­ °ü·Ã ÇÁ·Î±×·¥ÀÌ Á״´Ù. 14_1023 17:57:08 sunk hMsgHook_ := 0; hShellHook_ := 0; end; Result := 0; end; function InstallPrintHook: Integer; begin Result := -1; if Assigned(_PrintHook) then Result := _PrintHook.InstallHook; end; function UninstallPrintHook: Integer; begin Result := -1; if Assigned(_PrintHook) then Result := _PrintHook.UnInstallHook; end; exports InstallPrintHook, UninstallPrintHook; end.