677 lines
23 KiB
Plaintext
677 lines
23 KiB
Plaintext
{*******************************************************}
|
|
{ }
|
|
{ WindowCatchWndMsg }
|
|
{ }
|
|
{ Copyright (C) 2012 sunk }
|
|
{ }
|
|
{*******************************************************}
|
|
|
|
unit WindowCatchWndMsg;
|
|
|
|
interface
|
|
|
|
uses
|
|
System.SysUtils, System.Classes, Winapi.Windows, Winapi.Messages,
|
|
Tocsg.CommonData, Tocsg.DllEntry, Tocsg.Trace;
|
|
|
|
///////////////////////////////////////////////////////////////////////////////////////
|
|
// 전역 후킹 DLL 만들때 주의 사항 14_1027 16:43:37 sunk
|
|
// 예전에 컴파일해서 잘되던 전역 후킹 DLL을 새로 컴파일 해서 사용 하는중
|
|
// 로드까지 해서 후킹기능을 잘 이용하는데 해제할때 후커가 걸렸던
|
|
// 프로그램이 뒈지던 문제가 있었다. (물론 예전 버전은 잘돌아가고..)
|
|
// 해결(삽질)을 하던중 눈에 띄는 차이점이 생성된 DLL 크기가 많이 달랐는데
|
|
// Sunk.Debug에 아무 생각없이 추가한 Sunk.Smart, Sunk.Path 때문에
|
|
// 크기가 늘어나기도 했고, 전역 후커로써 사용하면 안되는 API가 포함 되어 있었나 보다
|
|
// Sunk.Debug에서 Sunk.Smart, Sunk.Path 이거 두개 빼니깐 용량도 확줄고 예전처럼 잘됨..
|
|
///////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
const
|
|
WM_WNDHOOK_RELOAD = WM_USER + 9630;
|
|
WM_WNDHOOK_NOTIFY = WM_USER + 9633;
|
|
WM_MESSAGEHOOK_NOTIFY = WM_USER + 9636;
|
|
|
|
WND_STATE_ATTACH_HOOK = 1;
|
|
WND_STATE_DETACH_HOOK = 2;
|
|
WND_STATE_ACTIVATE = 3;
|
|
WND_STATE_WINDOW_MIN = 4;
|
|
WND_STATE_WINDOW_MAX = 5;
|
|
WND_STATE_WINDOW_MOVESIZE = 6;
|
|
WND_STATE_REDRAW_TITLE = 7;
|
|
WND_STATE_CREATE_MAIN = 8;
|
|
WND_STATE_DESTROY_MAIN = 9;
|
|
WND_STATE_WINDOW_NORMAL = 10;
|
|
WND_STATE_ACTIVATE2 = 11; // for CBT 2014-04-08
|
|
|
|
MSG_WM_COPY = 21;
|
|
MSG_WM_CUT = 22;
|
|
MSG_WM_PASTE = 23;
|
|
MSG_WM_RENDERFORMAT = 24;
|
|
MSG_WM_RENDERALLFORMATS = 25;
|
|
MSG_WM_CLOSE = 26;
|
|
MSG_WM_QUIT = 27;
|
|
MSG_WM_DESTROY = 28;
|
|
MSG_WM_SETTEXT = 29;
|
|
|
|
type
|
|
THookState = (hsFree, hsHooking, hsReload, hsFinish);
|
|
PSharedData = ^TSharedData;
|
|
TSharedData = packed record
|
|
hRcvWnd: ULONGLONG;
|
|
dwLastInput: DWORD;
|
|
// HookState: THookState;
|
|
end;
|
|
|
|
// PWndActiveStruct = ^TWndActiveStruct;
|
|
// TWndActiveStruct = packed record
|
|
// nCode: Integer;
|
|
// hWindow: HWND;
|
|
// end;
|
|
|
|
// PHWND = ^HWND;
|
|
|
|
TWindowCatchWndMsg = class(TKuDllEntry)
|
|
private
|
|
SharedData_: TTgFileMapping<TSharedData>;
|
|
|
|
hCbtHook_,
|
|
hShellHook_,
|
|
hMessageHook_,
|
|
hCallWndHook_,
|
|
hMouseHook_,
|
|
hKeyboardHook_: HHook;
|
|
|
|
dtCreate_: TDateTime;
|
|
|
|
dwLastInputTickCount_: DWORD;
|
|
|
|
Trace_: TTgTrace;
|
|
|
|
function InstallWindowActiveHook: Integer;
|
|
function UnInstallWindowActiveHook: Integer;
|
|
public
|
|
Constructor Create;
|
|
Destructor Destroy; override;
|
|
|
|
procedure UpdateLastInput;
|
|
|
|
function SendWndHookMsg(wState: WORD; hWindow: HWND = 0): Boolean;
|
|
function SendMsgHookSimple(dwMsg: DWORD; hWindow: HWND): Boolean;
|
|
|
|
property CBTHook: HHook read hCbtHook_;
|
|
property ShellHook: HHook read hShellHook_;
|
|
property MessageHook: HHook read hMessageHook_;
|
|
property CallWndHook: HHook read hCallWndHook_;
|
|
property MouseHook: HHook read hMouseHook_;
|
|
property KeyboardHook: HHook read hKeyboardHook_;
|
|
property CreateDateTime: TDateTime read dtCreate_;
|
|
property SharedData: TTgFileMapping<TSharedData> read SharedData_;
|
|
end;
|
|
|
|
function process_WH_CBT(nCode: Integer; wParam: WPARAM; lParam: LPARAM): LRESULT; stdcall;
|
|
function process_WH_SHELL(nCode: Integer; wParam: WPARAM; lParam: LPARAM): LRESULT; stdcall;
|
|
function process_WH_GETMESSAGE(nCode: Integer; wParam: WPARAM; lParam: LPARAM): LRESULT; stdcall;
|
|
function process_WH_CALLWNDPROC(nCode: Integer; wParam: WPARAM; lParam: LPARAM): LRESULT; stdcall;
|
|
function process_WH_MOUSE(nCode: Integer; wParam: WPARAM; lParam: LPARAM): LRESULT; stdcall;
|
|
function process_WH_KEYBOARD(nCode: Integer; wParam: WPARAM; lParam: LPARAM): LRESULT; stdcall;
|
|
|
|
function InstallWindowActiveHook: Integer; export; stdcall; // 동시 실행 시 후킹 공유맵파일이 중복되기 때문에 이렇게 변경 함 16_0106 09:48:04 sunk
|
|
function UnInstallWindowActiveHook: Integer; export; stdcall;
|
|
|
|
procedure OutLog(const sLog: String); overload;
|
|
procedure OutLog(const Format: string; const Args: array of const); overload;
|
|
|
|
implementation
|
|
|
|
uses
|
|
Tocsg.KERNEL32, DefineWndMon;
|
|
|
|
//uses
|
|
// Tocsg.Path; // 이거 절대 포함 시켜선 안된다 16_0106 10:36:34 sunk
|
|
|
|
var
|
|
_WindowActiveHook: TWindowCatchWndMsg = nil;
|
|
|
|
procedure OutLog(const sLog: String);
|
|
begin
|
|
{$IFDEF DEBUG}
|
|
OutputDebugString(PChar(sLog));
|
|
{$ENDIF}
|
|
end;
|
|
|
|
procedure OutLog(const Format: string; const Args: array of const);
|
|
var
|
|
str: String;
|
|
begin
|
|
{$IFDEF DEBUG}
|
|
FmtStr(str, Format, Args);
|
|
OutLog(str);
|
|
{$ENDIF}
|
|
end;
|
|
|
|
function GetTitle(h: HWND): String;
|
|
var
|
|
str: array [0..255] of Char;
|
|
begin
|
|
GetWindowText(h, str, 256);
|
|
Result := str;
|
|
end;
|
|
|
|
function process_WH_CBT(nCode: Integer; wParam: WPARAM; lParam: LPARAM): LRESULT;
|
|
var
|
|
pCreateWnd: PCBTCreateWnd;
|
|
// pActivateWnd: PCBTActivateStruct;
|
|
pMouse: PMouseHookStruct;
|
|
begin
|
|
if Assigned(_WindowActiveHook) then
|
|
begin
|
|
try
|
|
try
|
|
if nCode >= HC_ACTION then
|
|
case nCode of
|
|
HCBT_CREATEWND : // 윈도우가 생성된 경우다, WM_CREATE, WM_NCCREATE 프로시저가 아직 수행되지 않은 단계
|
|
begin
|
|
// 윈도우 생성로그는 메인만 남기도록 함. 2012-05-16 sunk
|
|
// if gWindowActiveHook.OwnerWindow <> wParam then
|
|
// begin
|
|
// pCreateWnd := PCBTCreateWnd(lParam);
|
|
// if pCreateWnd.lpcs.lpszName <> '' then
|
|
// OutLog('[%s] process_WH_CBT >> HCBT_CREATEWND >> Name = %s', [gWindowActiveHook.ModuleName, pCreateWnd.lpcs.lpszName]);
|
|
// end;
|
|
end;
|
|
HCBT_DESTROYWND : ; // 윈도우가 파괴된 경우다
|
|
HCBT_ACTIVATE : // 윈도우가 활성화 된 경우다
|
|
begin
|
|
_WindowActiveHook.SendWndHookMsg(WND_STATE_ACTIVATE2, wParam); // 막음 16_0811 09:54:17 sunk
|
|
{
|
|
gWindowActiveHook.hMain_ := wParam;
|
|
gWindowActiveHook.SendMsg(WM_WAH_ACTIVATE, wParam);
|
|
// pActivateWnd := PCBTActivateStruct(lParam);
|
|
// OutLog('[%s] process_WH_CBT >> HCBT_ACTIVATE >> Mouse = %d >> Title = %s', [gWindowActiveHook.ModuleName, Integer(pActivateWnd.fMouse), GetTitle(wParam)]);
|
|
OutLog('[%s] process_WH_CBT >> HCBT_ACTIVATE >> Title = %s', [gWindowActiveHook.ModuleName, GetTitle(wParam)]);
|
|
}
|
|
end;
|
|
HCBT_CLICKSKIPPED : // 마우스 메시지가 시스템 메시지에서 제거된 경우다
|
|
begin
|
|
// pMouse := PMouseHookStruct(lParam);
|
|
// OutLog('[%s] process_WH_CBT >> HCBT_CLICKSKIPPED >> HitTestCode = %d >> Title = %s', [gWindowActiveHook.ModuleName, pMouse.wHitTestCode, GetTitle(pMouse.hwnd)]);
|
|
end;
|
|
HCBT_KEYSKIPPED : // 키보드 메시지가 시스템 메시지 큐에서 제거된 경우다
|
|
begin
|
|
// OutLog('[%s] process_WH_CBT >> HCBT_KEYSKIPPED >> Title = %s', [gWindowActiveHook.ModuleName, GetTitle(wParam)]);
|
|
end;
|
|
HCBT_MINMAX : // 윈도우가 최소화/최대화가 된 경우다
|
|
begin
|
|
case lParam of
|
|
SW_RESTORE : _WindowActiveHook.SendWndHookMsg(WND_STATE_WINDOW_NORMAL, wParam);
|
|
SW_MINIMIZE : _WindowActiveHook.SendWndHookMsg(WND_STATE_WINDOW_MIN, wParam);
|
|
SW_MAXIMIZE : _WindowActiveHook.SendWndHookMsg(WND_STATE_WINDOW_MAX, wParam);
|
|
end;
|
|
OutLog('[%s] process_WH_CBT >> HCBT_MINMAX >> Title = %s', [_WindowActiveHook.ModuleName, GetTitle(wParam)]);
|
|
end;
|
|
HCBT_MOVESIZE : // 윈도우가 옮겨지거나 크기가 변경된 경우다
|
|
begin
|
|
_WindowActiveHook.SendWndHookMsg(WND_STATE_WINDOW_MOVESIZE, wParam);
|
|
OutLog('[%s] process_WH_CBT >> HCBT_MOVESIZE >> Title = %s', [_WindowActiveHook.ModuleName, GetTitle(wParam)]);
|
|
end;
|
|
HCBT_QS : ; // 시스템 메시지 큐로부터 WM_QUEUESYNC 메시지를 전달받은 경우다
|
|
HCBT_SETFOCUS : // 윈도우가 키보드 포커스를 가지게 된 경우다
|
|
begin
|
|
// OutLog('[%s] process_WH_CBT >> HCBT_SETFOCUS >> Title = %s, Pre = %s', [gWindowActiveHook.ModuleName, GetTitle(wParam), GetTitle(lParam)]);
|
|
end;
|
|
HCBT_SYSCOMMAND : ; // 시스템 명령(WM_SYSCOMMAND)이 수행되는 경우다
|
|
end;
|
|
except
|
|
exit;
|
|
end;
|
|
finally
|
|
Result := CallNextHookEx(_WindowActiveHook.CBTHook, 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;
|
|
begin
|
|
if Assigned(_WindowActiveHook) then
|
|
begin
|
|
try
|
|
try
|
|
if nCode >= HC_ACTION then
|
|
case nCode of
|
|
HSHELL_ACCESSIBILITYSTATE : ; // Windows 2000/XP: accessibility 상태가 변경되었음
|
|
HSHELL_APPCOMMAND : ; // Windows 2000/XP: 사용자의 입력 이벤트에 의해서 WM_APPCOMMAND 가 발생한 경우다
|
|
HSHELL_ACTIVATESHELLWINDOW : ; // 쉘 메인 윈도우가 활성화 되어야 하는 경우다
|
|
HSHELL_GETMINRECT : // 윈도우가 최소화/최대화된 경우다
|
|
begin
|
|
OutLog('[%s] process_WH_SHELL >> HSHELL_GETMINRECT', [_WindowActiveHook.ModuleName]);
|
|
end;
|
|
HSHELL_LANGUAGE : ; // 키보드 언어가 변경되거나 새로운 키보드 레이아웃이 로드된 경우다
|
|
HSHELL_REDRAW : // 태스크바에 있는 윈도우 타이틀이 새로 그려지는 경우다
|
|
begin
|
|
_WindowActiveHook.SendWndHookMsg(WND_STATE_REDRAW_TITLE, wParam);
|
|
OutLog('[%s] process_WH_SHELL >> HSHELL_REDRAW >> Title = %s', [_WindowActiveHook.ModuleName, GetTitle(wParam)]);
|
|
end;
|
|
HSHELL_TASKMAN : // 사용자가 태스크 리스트를 선택한 경우다. 테스트해 본 결과 Ctrl + Esc 키를 누른 경우 훅 프로시저가 호출되었다. 시작 버튼을 눌렀을 때엔 호출되지 않는다
|
|
begin
|
|
OutLog('[%s] process_WH_SHELL >> HSHELL_TASKMAN', [_WindowActiveHook.ModuleName]);
|
|
end;
|
|
HSHELL_WINDOWACTIVATED : // 탑 레벨 윈도우의 활성화 상태가 변경된 경우다
|
|
begin
|
|
OutLog('[%s] process_WH_CBT >> HCBT_ACTIVATE >> Title = %s', [_WindowActiveHook.ModuleName, GetTitle(wParam)]);
|
|
_WindowActiveHook.SendWndHookMsg(WND_STATE_ACTIVATE, wParam);
|
|
end;
|
|
HSHELL_WINDOWCREATED : // 탑 레벨 윈도우가 생성된 경우다. 이 훅이 호출되는 시점에 윈도우는 생성된 상태다
|
|
begin
|
|
_WindowActiveHook.SendWndHookMsg(WND_STATE_CREATE_MAIN, wParam);
|
|
OutLog('[%s] process_WH_SHELL >> HSHELL_WINDOWCREATED >> Start = %s', [_WindowActiveHook.ModuleName,
|
|
DateTimeToStr(_WindowActiveHook.CreateDateTime)]);
|
|
end;
|
|
HSHELL_WINDOWDESTROYED : // 탑 레벨 윈도우가 파괴된 경우다. 이 훅이 호출되는 시점에 윈도우는 존재한다
|
|
begin
|
|
_WindowActiveHook.SendWndHookMsg(WND_STATE_DESTROY_MAIN, wParam);
|
|
OutLog('[%s] process_WH_SHELL >> HSHELL_WINDOWDESTROYED >> Start = %s, End = %s', [_WindowActiveHook.ModuleName,
|
|
DateTimeToStr(_WindowActiveHook.CreateDateTime), DateTimeToStr(now)]);
|
|
end;
|
|
HSHELL_WINDOWREPLACED : ; // Windows XP: 탑 레벨 윈도우가 대체(replaced)된 경우다
|
|
end;
|
|
except
|
|
exit;
|
|
end;
|
|
finally
|
|
Result := CallNextHookEx(_WindowActiveHook.ShellHook, nCode, wParam, lParam);
|
|
end;
|
|
end else
|
|
Result := 0;//CallNextHookEx(0, nCode, wParam, lParam);
|
|
end;
|
|
|
|
function process_WH_GETMESSAGE(nCode: Integer; wParam: WPARAM; lParam: LPARAM): LRESULT;
|
|
begin
|
|
if Assigned(_WindowActiveHook) then
|
|
begin
|
|
try
|
|
// try
|
|
// if nCode >= 0 then
|
|
// begin
|
|
// case PMSG(lParam).message of
|
|
// WM_COPY : _WindowActiveHook.SendMsgHookSimple(MSG_WM_COPY);
|
|
// WM_CUT : _WindowActiveHook.SendMsgHookSimple(MSG_WM_CUT);
|
|
// WM_PASTE : _WindowActiveHook.SendMsgHookSimple(MSG_WM_PASTE);
|
|
// WM_RENDERFORMAT : _WindowActiveHook.SendMsgHookSimple(MSG_WM_RENDERFORMAT);
|
|
// WM_RENDERALLFORMATS : _WindowActiveHook.SendMsgHookSimple(MSG_WM_RENDERALLFORMATS);
|
|
// end;
|
|
// end;
|
|
// except
|
|
// exit;
|
|
// end;
|
|
finally
|
|
Result := CallNextHookEx(_WindowActiveHook.MessageHook, nCode, wParam, lParam);
|
|
end;
|
|
end else
|
|
Result := 0;//CallNextHookEx(0, nCode, wParam, lParam);
|
|
end;
|
|
|
|
function process_WH_CALLWNDPROC(nCode: Integer; wParam: WPARAM; lParam: LPARAM): LRESULT;
|
|
begin
|
|
if Assigned(_WindowActiveHook) then
|
|
begin
|
|
try
|
|
try
|
|
if nCode >= 0 then
|
|
case PCWPSTRUCT(lParam).message of
|
|
WM_COPY : _WindowActiveHook.SendMsgHookSimple(MSG_WM_COPY, PCWPSTRUCT(lParam).hwnd);
|
|
WM_CUT : _WindowActiveHook.SendMsgHookSimple(MSG_WM_CUT, PCWPSTRUCT(lParam).hwnd);
|
|
WM_PASTE : _WindowActiveHook.SendMsgHookSimple(MSG_WM_PASTE, PCWPSTRUCT(lParam).hwnd);
|
|
WM_RENDERFORMAT : _WindowActiveHook.SendMsgHookSimple(MSG_WM_RENDERFORMAT, PCWPSTRUCT(lParam).hwnd);
|
|
WM_RENDERALLFORMATS : _WindowActiveHook.SendMsgHookSimple(MSG_WM_RENDERALLFORMATS, PCWPSTRUCT(lParam).hwnd);
|
|
// WM_CLOSE : _WindowActiveHook.SendMsgHookSimple(MSG_WM_CLOSE, PCWPSTRUCT(lParam).hwnd);
|
|
// WM_QUIT : _WindowActiveHook.SendMsgHookSimple(MSG_WM_QUIT, PCWPSTRUCT(lParam).hwnd);
|
|
WM_DESTROY : _WindowActiveHook.SendMsgHookSimple(MSG_WM_DESTROY, PCWPSTRUCT(lParam).hwnd); // 윈도우, 크롬 서브 폼 종료될땐 이걸 사용하는군 16_0203 15:19:17 sunk
|
|
WM_SETTEXT : _WindowActiveHook.SendMsgHookSimple(MSG_WM_SETTEXT, PCWPSTRUCT(lParam).hwnd);
|
|
end;
|
|
except
|
|
exit;
|
|
end;
|
|
finally
|
|
Result := CallNextHookEx(_WindowActiveHook.MessageHook, nCode, wParam, lParam);
|
|
end;
|
|
end else
|
|
Result := 0;//CallNextHookEx(0, nCode, wParam, lParam);
|
|
end;
|
|
|
|
function process_WH_MOUSE(nCode: Integer; wParam: WPARAM; lParam: LPARAM): LRESULT;
|
|
begin
|
|
if Assigned(_WindowActiveHook) then
|
|
begin
|
|
try
|
|
try
|
|
if nCode >= HC_ACTION then
|
|
case wParam of
|
|
WM_LBUTTONDOWN,
|
|
WM_RBUTTONDOWN,
|
|
WM_LBUTTONDBLCLK,
|
|
WM_RBUTTONDBLCLK,
|
|
WM_MBUTTONDOWN,
|
|
WM_MBUTTONDBLCLK,
|
|
WM_NCLBUTTONDOWN,
|
|
WM_NCRBUTTONDOWN,
|
|
WM_NCMBUTTONDOWN,
|
|
// WM_MOUSEHOVER,
|
|
// WM_MOUSELEAVE,
|
|
WM_MOUSEWHEEL : _WindowActiveHook.UpdateLastInput;
|
|
end;
|
|
except
|
|
exit;
|
|
end;
|
|
finally
|
|
Result := CallNextHookEx(_WindowActiveHook.MouseHook, nCode, wParam, lParam);
|
|
end;
|
|
end else
|
|
Result := 0;//CallNextHookEx(0, nCode, wParam, lParam);
|
|
end;
|
|
|
|
function process_WH_KEYBOARD(nCode: Integer; wParam: WPARAM; lParam: LPARAM): LRESULT;
|
|
var
|
|
bPreDown,
|
|
bKeyDown: Boolean;
|
|
begin
|
|
if Assigned(_WindowActiveHook) then
|
|
begin
|
|
try
|
|
try
|
|
if nCode >= HC_ACTION then
|
|
begin
|
|
bPreDown := (lParam and $40000000) <> 0; // 키를 계속 누르고 있는 상태인가 아닌가
|
|
bKeyDown := (lParam and $80000000) = 0; // 키 다운인가 아닌가
|
|
|
|
if not bPreDown and bKeyDown then
|
|
_WindowActiveHook.UpdateLastInput;
|
|
end;
|
|
except
|
|
exit;
|
|
end;
|
|
finally
|
|
Result := CallNextHookEx(_WindowActiveHook.KeyboardHook, nCode, wParam, lParam);
|
|
end;
|
|
end else
|
|
Result := 0;//CallNextHookEx(0, nCode, wParam, lParam);
|
|
end;
|
|
|
|
function InstallWindowActiveHook: Integer;
|
|
begin
|
|
Result := -1;
|
|
|
|
if Assigned(_WindowActiveHook) then
|
|
Result := _WindowActiveHook.InstallWindowActiveHook;
|
|
end;
|
|
|
|
function UnInstallWindowActiveHook: Integer;
|
|
begin
|
|
Result := -1;
|
|
|
|
if Assigned(_WindowActiveHook) then
|
|
begin
|
|
// if _WindowActiveHook.SharedData.IsAvailable then
|
|
// _WindowActiveHook.SharedData.Data.HookState := hsFinish;
|
|
Result := _WindowActiveHook.UnInstallWindowActiveHook;
|
|
end;
|
|
end;
|
|
|
|
{ TWindowCatchWndMsg }
|
|
|
|
Constructor TWindowCatchWndMsg.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
|
|
sAddMapName: String;
|
|
|
|
begin
|
|
Inherited Create;
|
|
|
|
Trace_ := nil;
|
|
{$IFDEF DEBUG}
|
|
var sPath: String := ParamStr(0);
|
|
Trace_ := TTgTrace.Create(ExtractFilePath(sPath), ExtractFileName(sPath) + '.log', false);
|
|
{$ELSE}
|
|
Trace_ := TTgTrace.Create;
|
|
{$ENDIF}
|
|
|
|
ASSERT(_WindowActiveHook = nil);
|
|
_WindowActiveHook := self;
|
|
|
|
hCbtHook_ := 0;
|
|
hShellHook_ := 0;
|
|
hMessageHook_ := 0;
|
|
hCallWndHook_ := 0;
|
|
hMouseHook_ := 0;
|
|
hKeyboardHook_ := 0;
|
|
|
|
dwLastInputTickCount_ := 0;
|
|
|
|
GetStartTime;
|
|
|
|
sAddMapName := DllName;
|
|
if sAddMapName <> '' then
|
|
sAddMapName := StringReplace(sAddMapName, '64', '', [rfReplaceAll]);
|
|
|
|
SharedData_ := TTgFileMapping<TSharedData>.Create(MAP_FILENAME_WM + sAddMapName, SizeOf(TSharedData));
|
|
SharedData_.DoFreeData := false; // 추가 15_0911 10:39:41 sunk
|
|
if SharedData_.LastError = ERROR_SUCCESS then
|
|
SendWndHookMsg(WND_STATE_ATTACH_HOOK);
|
|
end;
|
|
|
|
Destructor TWindowCatchWndMsg.Destroy;
|
|
begin
|
|
SendWndHookMsg(WND_STATE_DETACH_HOOK);
|
|
|
|
UnInstallWindowActiveHook;
|
|
|
|
_WindowActiveHook := nil;
|
|
|
|
Inherited;
|
|
|
|
FreeAndNil(SharedData_);
|
|
|
|
if Assigned(Trace_) then
|
|
FreeAndNil(Trace_);
|
|
end;
|
|
|
|
procedure TWindowCatchWndMsg.UpdateLastInput;
|
|
begin
|
|
if SharedData_.IsAvailable then
|
|
SharedData_.Data.dwLastInput := GetTickCount;
|
|
end;
|
|
|
|
function TWindowCatchWndMsg.SendWndHookMsg(wState: WORD; hWindow: HWND): Boolean;
|
|
begin
|
|
Result := false;
|
|
if SharedData_.IsAvailable then
|
|
begin
|
|
try
|
|
if wState = WND_STATE_ATTACH_HOOK then
|
|
PostMessage(SharedData_.Data.hRcvWnd, WM_WNDHOOK_NOTIFY, MakeWParam(wState, PID), PID)
|
|
else
|
|
PostMessage(SharedData_.Data.hRcvWnd, WM_WNDHOOK_NOTIFY, MakeWParam(wState, PID), hWindow);
|
|
Result := true;
|
|
// OutLog('[%s] TWindowCatchWndMsg >> SendMsg() >> H = %d, M = %d', [ModuleName, SharedData_.Data.hRcvWnd, wState]);
|
|
except
|
|
//
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
function TWindowCatchWndMsg.SendMsgHookSimple(dwMsg: DWORD; hWindow: HWND): Boolean;
|
|
begin
|
|
Result := false;
|
|
if SharedData_.IsAvailable then
|
|
begin
|
|
try
|
|
PostMessage(SharedData_.Data.hRcvWnd, WM_MESSAGEHOOK_NOTIFY, dwMsg, hWindow);
|
|
Result := true;
|
|
// OutLog('[%s] TWindowCatchWndMsg >> SendMsg() >> H = %d, M = %d', [ModuleName, SharedData_.Data.hRcvWnd, wState]);
|
|
except
|
|
//
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
function TWindowCatchWndMsg.InstallWindowActiveHook: Integer;
|
|
begin
|
|
TTgTrace.t('[%s] TWindowCatchWndMsg >> InstallWindowActiveHook()', [ModuleName]);
|
|
// UnInstallWindowActiveHook;
|
|
|
|
Result := 0;
|
|
|
|
// Active 한번 더 자세히 잡으려고 추가 sunk
|
|
// 이거 활성화 하고 UnInstallWindowActiveHook()를 수행하면 64비트 환경에서 explorer.exe가 죽는다.. 다른것도 죽겠지..
|
|
hCbtHook_ := SetWindowsHookEx(WH_CBT, process_WH_CBT, HInstance, 0);
|
|
if hCbtHook_ = 0 then
|
|
begin
|
|
TTgTrace.t('[%s] TWindowCatchWndMsg >> SetWindowsHookEx(WH_CBT) fail!!', [ModuleName]);
|
|
Result := 1;
|
|
exit;
|
|
end;
|
|
|
|
hShellHook_ := SetWindowsHookEx(WH_SHELL, process_WH_SHELL, HInstance, 0);
|
|
if hShellHook_ = 0 then
|
|
begin
|
|
TTgTrace.t('[%s] TWindowCatchWndMsg >> SetWindowsHookEx(WH_SHELL) fail!!', [ModuleName]);
|
|
Result := 2;
|
|
exit;
|
|
end;
|
|
|
|
// 필요 없으면 제외 16_0106 10:43:50 sunk
|
|
// hMessageHook_ := SetWindowsHookEx(WH_GETMESSAGE, process_WH_GETMESSAGE, HInstance, 0);
|
|
// if hMessageHook_ = 0 then
|
|
// begin
|
|
// TTgTrace.t('[%s] TWindowCatchWndMsg >> SetWindowsHookEx(WH_GETMESSAGE) fail!!', [ModuleName]);
|
|
// Result := 5;
|
|
// exit;
|
|
// end;
|
|
|
|
// hCallWndHook_ := SetWindowsHookEx(WH_CALLWNDPROC, process_WH_CALLWNDPROC, HInstance, 0);
|
|
// if hCallWndHook_ = 0 then
|
|
// begin
|
|
// TTgTrace.t('[%s] TWindowCatchWndMsg >> SetWindowsHookEx(WH_CALLWNDPROC) fail!!', [ModuleName]);
|
|
// Result := 5;
|
|
// exit;
|
|
// end;
|
|
|
|
// 필요하지 않으면 제외시킨다. 14_1030 13:25:41 sunk
|
|
// hMouseHook_, hKeyboardHook_ 퀘이터, 시큐인에서 사용함
|
|
// hMouseHook_ := SetWindowsHookEx(WH_MOUSE, process_WH_MOUSE, HInstance, 0);
|
|
// if hMouseHook_ = 0 then
|
|
// begin
|
|
// TTgTrace.t('[%s] TWindowCatchWndMsg >> SetWindowsHookEx(WH_MOUSE) fail!!', [ModuleName]);
|
|
// Result := 3;
|
|
// exit;
|
|
// end;
|
|
|
|
// 퀘이터에서 사용하지 않음 16_0111 09:15:35 sunk
|
|
// hKeyboardHook_ := SetWindowsHookEx(WH_KEYBOARD, process_WH_KEYBOARD, HInstance, 0);
|
|
// if hKeyboardHook_ = 0 then
|
|
// begin
|
|
// TTgTrace.t('[%s] TWindowCatchWndMsg >> SetWindowsHookEx(WH_KEYBOARD) fail!!', [ModuleName]);
|
|
// Result := 4;
|
|
// exit;
|
|
// end;
|
|
end;
|
|
|
|
function TWindowCatchWndMsg.UnInstallWindowActiveHook: Integer;
|
|
begin
|
|
TTgTrace.t('[%s] TWindowCatchWndMsg >> UnInstallWindowActiveHook()', [ModuleName]);
|
|
Result := 0;
|
|
|
|
try
|
|
if hKeyboardHook_ <> 0 then
|
|
begin
|
|
TTgTrace.t('[%s] TWindowCatchWndMsg >> UnhookWindowsHookEx(hKeybordHook_)', [ModuleName]);
|
|
UnhookWindowsHookEx(hKeyboardHook_);
|
|
hKeyboardHook_ := 0;
|
|
end;
|
|
except
|
|
// 왜인지.. OS 마다다른건지 모르겠지만, 오류를 발생해서 관련 프로그램이 죽는다. 14_1023 17:57:08 sunk
|
|
hKeyboardHook_ := 0;
|
|
end;
|
|
|
|
try
|
|
if hMouseHook_ <> 0 then
|
|
begin
|
|
TTgTrace.t('[%s] TWindowCatchWndMsg >> UnhookWindowsHookEx(hMouseHook_)', [ModuleName]);
|
|
UnhookWindowsHookEx(hMouseHook_);
|
|
hMouseHook_ := 0;
|
|
end;
|
|
except
|
|
// 왜인지.. OS 마다다른건지 모르겠지만, 오류를 발생해서 관련 프로그램이 죽는다. 14_1023 17:57:08 sunk
|
|
hMouseHook_ := 0;
|
|
end;
|
|
|
|
try
|
|
if hCallWndHook_ <> 0 then
|
|
begin
|
|
TTgTrace.t('[%s] TWindowCatchWndMsg >> UnhookWindowsHookEx(CallWndHook)', [ModuleName]);
|
|
UnhookWindowsHookEx(hCallWndHook_);
|
|
hCallWndHook_ := 0;
|
|
end;
|
|
except
|
|
// 왜인지.. OS 마다다른건지 모르겠지만, 오류를 발생해서 관련 프로그램이 죽는다. 14_1023 17:57:08 sunk
|
|
hCallWndHook_ := 0;
|
|
end;
|
|
|
|
try
|
|
if hMessageHook_ <> 0 then
|
|
begin
|
|
TTgTrace.t('[%s] TWindowCatchWndMsg >> UnhookWindowsHookEx(GetMessageHook)', [ModuleName]);
|
|
UnhookWindowsHookEx(hMessageHook_);
|
|
hMessageHook_ := 0;
|
|
end;
|
|
except
|
|
// 왜인지.. OS 마다다른건지 모르겠지만, 오류를 발생해서 관련 프로그램이 죽는다. 14_1023 17:57:08 sunk
|
|
hMessageHook_ := 0;
|
|
end;
|
|
|
|
try
|
|
if hShellHook_ <> 0 then
|
|
begin
|
|
TTgTrace.t('[%s] TWindowCatchWndMsg >> UnhookWindowsHookEx(ShellHook)', [ModuleName]);
|
|
UnhookWindowsHookEx(hShellHook_);
|
|
hShellHook_ := 0;
|
|
end;
|
|
except
|
|
// 왜인지.. OS 마다다른건지 모르겠지만, 오류를 발생해서 관련 프로그램이 죽는다. 14_1023 17:57:08 sunk
|
|
hShellHook_ := 0;
|
|
end;
|
|
|
|
try
|
|
if hCbtHook_ <> 0 then
|
|
begin
|
|
TTgTrace.t('[%s] TWindowCatchWndMsg >> UnhookWindowsHookEx(CbtHook)', [ModuleName]);
|
|
UnhookWindowsHookEx(hCbtHook_);
|
|
hCbtHook_ := 0;
|
|
end;
|
|
except
|
|
// 왜인지.. OS 마다다른건지 모르겠지만, 오류를 발생해서 관련 프로그램이 죽는다. 14_1023 17:57:08 sunk
|
|
hCbtHook_ := 0;
|
|
end;
|
|
end;
|
|
|
|
exports
|
|
InstallWindowActiveHook, UnInstallWindowActiveHook;
|
|
|
|
end.
|