You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
RnQ/RnQ/hook.pas

219 lines
6.0 KiB
Plaintext

{
This file is part of R&Q.
Under same license
}
unit hook;
{$I RnQConfig.inc}
interface
uses
Winapi.Windows, Winapi.Messages, System.Classes, System.SysUtils, Vcl.Forms;
{$I NoRTTI.inc}
procedure InstallMainHook;
procedure InstallSessionHook;
procedure UninstallSessionHook;
function IsMoved(awTime: Integer = -1): Boolean;
type
TMessageHandler = class
function MainWindowHook(var Message: TMessage): Boolean;
end;
var
IsHooked: Boolean = False;
IsLocked: Boolean = False;
WM_FINDINSTANCE: Integer;
function RegisterSessionNotification(Wnd: HWND; dwFlags: DWORD): Boolean;
function UnRegisterSessionNotification(Wnd: HWND): Boolean;
implementation
uses
GlobalLib, UtilLib, RnQMacros, SciterLib, CLBox;
const
// Only session notifications involving the session attached to by the window
// identified by the hWnd parameter value are to be received.
NOTIFY_FOR_THIS_SESSION = 0;
// All session notifications are to be received.
NOTIFY_FOR_ALL_SESSIONS = 1;
var
MsgHandler: TMessageHandler;
FRegisteredSessionNotification: Boolean = False;
GetLII: function(var plii: TLastInputInfo): BOOL; stdcall;
procedure InstallMainHook;
begin
Application.HookMainWindow(MsgHandler.MainWindowHook);
end;
procedure InstallSessionHook;
var
hndl: THandle;
begin
FRegisteredSessionNotification := RegisterSessionNotification(Application.Handle, NOTIFY_FOR_THIS_SESSION);
if Win32MajorVersion >= 5 then
begin
hndl := GetModuleHandle('user32.dll');
@GetLII := GetProcAddress(hndl, 'GetLastInputInfo');
if @GetLII = nil then
Exit;
IsHooked := True;
end
end;
procedure UninstallSessionHook;
begin
if not IsHooked then
Exit;
if FRegisteredSessionNotification then
UnRegisterSessionNotification(Application.Handle);
IsHooked := False;
end;
function LastInput: DWORD;
var
LInput: TLastInputInfo;
begin
LInput.cbSize := SizeOf(TLastInputInfo);
GetLII(LInput);
Result := GetTickCount - LInput.dwTime;
end;
function IsMoved(awTime: Integer = -1): Boolean;
begin
Result := false;
if awTime < 0 then
awTime := autoaway.time;
if (LastInput + 5 < awTime) then
Result := True;
end;
function RegisterSessionNotification(Wnd: HWND; dwFlags: DWORD): Boolean;
// The RegisterSessionNotification function registers the specified window
// to receive session change notifications.
// Parameters:
// hWnd: Handle of the window to receive session change notifications.
// dwFlags: Specifies which session notifications are to be received:
// (NOTIFY_FOR_THIS_SESSION, NOTIFY_FOR_ALL_SESSIONS)
type
TWTSRegisterSessionNotification = function(Wnd: HWND; dwFlags: DWORD): BOOL; stdcall;
var
hWTSapi32dll: THandle;
WTSRegisterSessionNotification: TWTSRegisterSessionNotification;
begin
Result := false;
hWTSapi32dll := LoadLibrary('Wtsapi32.dll');
if (hWTSapi32dll > 0) then
begin
try
@WTSRegisterSessionNotification := GetProcAddress(hWTSapi32dll, 'WTSRegisterSessionNotification');
if Assigned(WTSRegisterSessionNotification) then
Result := WTSRegisterSessionNotification(Wnd, dwFlags);
finally
if hWTSapi32dll > 0 then
FreeLibrary(hWTSapi32dll);
end;
end;
end;
function UnRegisterSessionNotification(Wnd: HWND): Boolean;
type
TWTSUnRegisterSessionNotification = function(Wnd: HWND): BOOL; stdcall;
var
hWTSapi32dll: THandle;
WTSUnRegisterSessionNotification: TWTSUnRegisterSessionNotification;
begin
Result := false;
hWTSapi32dll := LoadLibrary('Wtsapi32.dll');
if (hWTSapi32dll > 0) then
begin
try
@WTSUnRegisterSessionNotification := GetProcAddress(hWTSapi32dll, 'WTSUnRegisterSessionNotification');
if Assigned(WTSUnRegisterSessionNotification) then
Result := WTSUnRegisterSessionNotification(Wnd);
finally
if hWTSapi32dll > 0 then
FreeLibrary(hWTSapi32dll);
end;
end;
end;
function TMessageHandler.MainWindowHook(var Message: TMessage): Boolean;
var
Len: Integer;
Data: String;
Size: TFormPos;
begin
Result := False;
if Message.Msg = WM_FINDINSTANCE then
begin
Message.Result := 1337;
Result := True;
end else
case Message.Msg of
WM_HANDLEICQLINK:
begin
SetLength(Data, MAX_PATH);
Len := GlobalGetAtomName(Message.WParam, PChar(Data), MAX_PATH);
GlobalDeleteAtom(Message.WParam);
SetLength(Data, Len);
ProcessICQLink(Data);
Result := True;
end;
WM_HOTKEY:
begin
if HotkeysEnabled and not Locked then
ExecuteMacro(Macros[Message.WParam].opcode);
Result := True;
end;
WM_WTSSESSION_CHANGE:
case Message.WParam of
WTS_CONSOLE_CONNECT: IsLocked := False;
WTS_CONSOLE_DISCONNECT: IsLocked := True;
WTS_REMOTE_CONNECT: IsLocked := False;
WTS_REMOTE_DISCONNECT: IsLocked := True;
WTS_SESSION_LOGON: IsLocked := False;
WTS_SESSION_LOGOFF: IsLocked := True;
WTS_SESSION_LOCK: IsLocked := True;
WTS_SESSION_UNLOCK: IsLocked := False;
end;
WM_DISPLAYCHANGE:
begin
Len := GetActiveMonitorCount;
if not (LastMonCnt = Len) then
begin
LastMonCnt := Len;
if CLBox.MonPositions.TryGetValue(LastMonCnt, Size) then
begin
TThread.CreateAnonymousThread(procedure
begin
Sleep(1000);
TThread.Synchronize(nil, procedure
begin
if Assigned(UI) and Assigned(UI.CL) then
UI.CL.SetPosition(Size.Left, Size.Top);
end);
end).Start;
end;
end;
end;
WM_EXITSIZEMOVE:
UI.CL.SavePositionForCurrentMonitorCount;
end;
end;
initialization
WM_FINDINSTANCE := RegisterWindowMessage('Unique R&Q message');
MsgHandler := TMessageHandler.Create;
finalization
MsgHandler.Free;
end.