diff pidgin/win32/IdleTracker/idletrack.c @ 15374:5fe8042783c1

Rename gtk/ and libgaim/ to pidgin/ and libpurple/
author Sean Egan <seanegan@gmail.com>
date Sat, 20 Jan 2007 02:32:10 +0000
parents
children 75ffc646647f
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/pidgin/win32/IdleTracker/idletrack.c	Sat Jan 20 02:32:10 2007 +0000
@@ -0,0 +1,186 @@
+/*
+ *  idletrack.c
+ *
+ *  Authors: mrgentry @ http://www.experts-exchange.com
+ *           Herman Bloggs <hermanator12002@yahoo.com>
+ *  Date: February, 2003
+ *  Description: Track user inactivity.
+ *
+ *  Andrew Whewell <awhewell@users.sourceforge.net> - 25th June 2004. Added
+ *  support for GetLastInputInfo under Windows 2000 and above. This avoids having
+ *  IDLETRACK.DLL hook itself into every process on the machine, which makes
+ *  upgrades easier. The hook mechanism is also used by key loggers, so not
+ *  using hooks doesn't put the willys up programs that keep an eye out for
+ *  loggers.
+ *
+ *  Windows 9x doesn't have GetLastInputInfo - when Gaim runs on these machines
+ *  the code silently falls back onto the old hooking scheme.
+ */
+#define _WIN32_WINNT 0x0500
+#include "idletrack.h"
+
+#define EXPORT __declspec(dllexport)
+
+static HANDLE hMapObject = NULL;
+static DWORD *lastTime = NULL;
+static HHOOK keyHook = NULL;
+static HHOOK mouseHook = NULL;
+static HINSTANCE g_hInstance = NULL;
+static POINT g_point;
+
+/* GetLastInputInfo address and module - if g_GetLastInputInfo == NULL then
+ * we fall back on the old "hook the world" method. GetLastInputInfo was brought
+ * in with Windows 2000 so Windows 9x will still hook everything.
+ */
+typedef BOOL (WINAPI *GETLASTINPUTINFO)(LASTINPUTINFO *);
+static HMODULE g_user32 = NULL;
+static GETLASTINPUTINFO g_GetLastInputInfo = NULL;
+
+static DWORD* setup_shared_mem() {
+	BOOL fInit;
+
+	/* Set up the shared memory. */
+	hMapObject = CreateFileMapping((HANDLE) 0xFFFFFFFF, /* use paging file        */
+								   NULL,                /* no security attributes */
+								   PAGE_READWRITE,      /* read/write access      */
+								   0,                   /* size: high 32-bits     */
+								   sizeof(DWORD),       /* size: low 32-bits      */
+								   "timermem");         /* name of map object     */
+
+	if(hMapObject == NULL)
+		return NULL;
+
+	/* The first process to attach initializes memory. */
+	fInit = (GetLastError() != ERROR_ALREADY_EXISTS);
+
+	/* Get a pointer to the file-mapped shared memory. */
+	lastTime = (DWORD*) MapViewOfFile(hMapObject,     /* object to map view of    */
+									  FILE_MAP_WRITE, /* read/write access        */
+									  0,              /* high offset:  map from   */
+									  0,              /* low offset:   beginning  */
+									  0);             /* default: map entire file */
+
+	if(lastTime == NULL)
+		return NULL;
+
+	*lastTime = GetTickCount();
+
+	return lastTime;
+}
+
+
+static LRESULT CALLBACK KeyboardProc(int code, WPARAM wParam, LPARAM lParam) {
+	if(!(code < 0)) {
+		if(lastTime == NULL)
+			lastTime = setup_shared_mem();
+
+		if(lastTime)
+			*lastTime = GetTickCount();
+	}
+	return CallNextHookEx(keyHook, code, wParam, lParam);
+}
+
+
+static LRESULT CALLBACK MouseProc(int code, WPARAM wParam, LPARAM lParam) {
+	/* We need to verify that the Mouse pointer has actually moved. */
+	if(!(code < 0) &&
+			!((g_point.x == ((MOUSEHOOKSTRUCT*) lParam)->pt.x) &&
+			(g_point.y == ((MOUSEHOOKSTRUCT*) lParam)->pt.y))) {
+		g_point.x = ((MOUSEHOOKSTRUCT*) lParam)->pt.x;
+		g_point.y = ((MOUSEHOOKSTRUCT*) lParam)->pt.y;
+
+		if(lastTime == NULL)
+			lastTime = setup_shared_mem();
+
+		if(lastTime)
+			*lastTime = GetTickCount();
+	}
+	return CallNextHookEx(mouseHook, code, wParam, lParam);
+}
+
+
+EXPORT DWORD wgaim_get_lastactive() {
+	DWORD result = 0;
+
+	/* If we have GetLastInputInfo then use it, otherwise use the hooks*/
+	if(g_GetLastInputInfo != NULL) {
+		LASTINPUTINFO lii;
+		memset(&lii, 0, sizeof(lii));
+		lii.cbSize = sizeof(lii);
+		if(g_GetLastInputInfo(&lii)) {
+			result = lii.dwTime;
+		}
+	} else {
+		if(lastTime == NULL)
+			lastTime = setup_shared_mem();
+
+		if(lastTime)
+			result = *lastTime;
+	}
+
+	return result;
+}
+
+
+EXPORT BOOL wgaim_set_idlehooks() {
+	/* Is GetLastInputInfo available?*/
+	g_user32 = LoadLibrary("user32.dll");
+	if(g_user32) {
+		g_GetLastInputInfo = (GETLASTINPUTINFO) GetProcAddress(g_user32, "GetLastInputInfo");
+	}
+
+	/* If we couldn't find GetLastInputInfo then fall back onto the hooking scheme*/
+	if(g_GetLastInputInfo == NULL) {
+		/* Set up the shared memory.*/
+		lastTime = setup_shared_mem();
+		if(lastTime == NULL)
+			return FALSE;
+		*lastTime = GetTickCount();
+
+	/* Set up the keyboard hook.*/
+		keyHook = SetWindowsHookEx(WH_KEYBOARD, KeyboardProc, g_hInstance, 0);
+		if(keyHook == NULL) {
+			UnmapViewOfFile(lastTime);
+			CloseHandle(hMapObject);
+			return FALSE;
+		}
+
+		/* Set up the mouse hook.*/
+		mouseHook = SetWindowsHookEx(WH_MOUSE, MouseProc, g_hInstance, 0);
+		if(mouseHook == NULL) {
+			UnhookWindowsHookEx(keyHook);
+			UnmapViewOfFile(lastTime);
+			CloseHandle(hMapObject);
+			return FALSE;
+		}
+	}
+
+	return TRUE;
+}
+
+
+EXPORT void wgaim_remove_idlehooks() {
+	if(g_user32 != NULL)
+		FreeLibrary(g_user32);
+	if(keyHook)
+		UnhookWindowsHookEx(keyHook);
+	if(mouseHook)
+		UnhookWindowsHookEx(mouseHook);
+	if(lastTime)
+		UnmapViewOfFile(lastTime);
+	if(hMapObject)
+		CloseHandle(hMapObject);
+}
+
+int WINAPI DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID lpReserved) {
+	switch(dwReason) {
+		case DLL_PROCESS_ATTACH:
+			g_hInstance = hInstance;
+			g_point.x = 0;
+			g_point.y = 0;
+			break;
+		case DLL_PROCESS_DETACH:
+			break;
+	}
+	return TRUE;
+}