Sat, 16 Apr 2005 18:44:40 +0000
[gaim-migrate @ 12503]
Fix bug #1016434 - "MSN phone numbers don't appear changed until next logon"
| 4533 | 1 | /* |
| 2 | * idletrack.c | |
| 3 | * | |
| 4 | * Authors: mrgentry @ http://www.experts-exchange.com | |
| 5 | * Herman Bloggs <hermanator12002@yahoo.com> | |
| 6 | * Date: February, 2003 | |
| 7 | * Description: Track user inactivity. | |
| 9417 | 8 | * |
| 9 | * Andrew Whewell <awhewell@users.sourceforge.net> - 25th June 2004. Added | |
| 10 | * support for GetLastInputInfo under Windows 2000 and above. This avoids having | |
| 11 | * IDLETRACK.DLL hook itself into every process on the machine, which makes | |
| 12 | * upgrades easier. The hook mechanism is also used by key loggers, so not | |
| 13 | * using hooks doesn't put the willys up programs that keep an eye out for | |
| 14 | * loggers. | |
| 15 | * | |
| 9419 | 16 | * Windows 9x doesn't have GetLastInputInfo - when Gaim runs on these machines |
| 9417 | 17 | * the code silently falls back onto the old hooking scheme. |
| 4533 | 18 | */ |
| 9417 | 19 | #define _WIN32_WINNT 0x0500 |
| 4533 | 20 | #include <windows.h> |
| 21 | ||
| 22 | #define EXPORT __declspec(dllexport) | |
| 23 | ||
| 24 | static HANDLE hMapObject = NULL; | |
| 25 | static DWORD *lastTime = NULL; | |
| 26 | static HHOOK keyHook = NULL; | |
| 27 | static HHOOK mouseHook = NULL; | |
| 28 | static HINSTANCE g_hInstance = NULL; | |
|
4548
f89a7e6e9508
[gaim-migrate @ 4827]
Herman Bloggs <herman@bluedigits.com>
parents:
4533
diff
changeset
|
29 | static POINT g_point; |
| 4533 | 30 | |
| 9418 | 31 | /* GetLastInputInfo address and module - if g_GetLastInputInfo == NULL then |
| 32 | * we fall back on the old "hook the world" method. GetLastInputInfo was brought | |
| 33 | * in with Windows 2000 so Windows 9x will still hook everything. | |
| 34 | */ | |
| 9417 | 35 | typedef BOOL (WINAPI *GETLASTINPUTINFO)(LASTINPUTINFO *); |
| 36 | static HMODULE g_user32 = NULL; | |
| 37 | static GETLASTINPUTINFO g_GetLastInputInfo = NULL; | |
| 38 | ||
| 4533 | 39 | static DWORD* setup_shared_mem() { |
| 40 | BOOL fInit; | |
| 41 | ||
| 9418 | 42 | /* Set up the shared memory. */ |
|
9865
8a8bdf9e9e08
[gaim-migrate @ 10744]
Mark Doliner <markdoliner@pidgin.im>
parents:
9863
diff
changeset
|
43 | /*hMapObject = CreateFileMapping((HANDLE) 0xFFFFFFFF, // use paging file |
|
8a8bdf9e9e08
[gaim-migrate @ 10744]
Mark Doliner <markdoliner@pidgin.im>
parents:
9863
diff
changeset
|
44 | NULL, // no security attributes |
|
8a8bdf9e9e08
[gaim-migrate @ 10744]
Mark Doliner <markdoliner@pidgin.im>
parents:
9863
diff
changeset
|
45 | PAGE_READWRITE, // read/write access |
|
8a8bdf9e9e08
[gaim-migrate @ 10744]
Mark Doliner <markdoliner@pidgin.im>
parents:
9863
diff
changeset
|
46 | 0, // size: high 32-bits |
|
8a8bdf9e9e08
[gaim-migrate @ 10744]
Mark Doliner <markdoliner@pidgin.im>
parents:
9863
diff
changeset
|
47 | sizeof(DWORD), // size: low 32-bits |
|
8a8bdf9e9e08
[gaim-migrate @ 10744]
Mark Doliner <markdoliner@pidgin.im>
parents:
9863
diff
changeset
|
48 | "timermem"); // name of map object |
| 9418 | 49 | */ |
| 50 | hMapObject = CreateFileMapping((HANDLE) 0xFFFFFFFF, | |
| 51 | NULL, | |
| 52 | PAGE_READWRITE, | |
| 53 | 0, | |
| 54 | sizeof(DWORD), | |
| 55 | "timermem"); | |
| 56 | ||
| 4533 | 57 | if (hMapObject == NULL) |
| 58 | return NULL; | |
| 9418 | 59 | |
| 60 | /* The first process to attach initializes memory. */ | |
| 4533 | 61 | fInit = (GetLastError() != ERROR_ALREADY_EXISTS); |
| 9418 | 62 | |
| 63 | /* Get a pointer to the file-mapped shared memory. */ | |
| 64 | /*lastTime = (DWORD*) MapViewOfFile(hMapObject, // object to map view of | |
| 65 | * FILE_MAP_WRITE, // read/write access | |
| 66 | * 0, // high offset: map from | |
| 67 | * 0, // low offset: beginning | |
| 68 | * 0); // default: map entire file | |
| 69 | */ | |
| 70 | lastTime = (DWORD*) MapViewOfFile(hMapObject, | |
| 71 | FILE_MAP_WRITE, | |
| 72 | 0, | |
| 73 | 0, | |
| 74 | 0); | |
| 75 | ||
| 4533 | 76 | if (lastTime == NULL) |
| 77 | return NULL; | |
| 9418 | 78 | |
| 4533 | 79 | *lastTime = GetTickCount(); |
| 9418 | 80 | |
| 4533 | 81 | return lastTime; |
| 82 | } | |
| 83 | ||
| 84 | ||
| 85 | LRESULT CALLBACK KeyboardProc(int code, WPARAM wParam, LPARAM lParam) { | |
|
6561
88ff258f78dd
[gaim-migrate @ 7083]
Herman Bloggs <herman@bluedigits.com>
parents:
5336
diff
changeset
|
86 | if (!(code < 0)) { |
|
88ff258f78dd
[gaim-migrate @ 7083]
Herman Bloggs <herman@bluedigits.com>
parents:
5336
diff
changeset
|
87 | if (lastTime == NULL) |
|
88ff258f78dd
[gaim-migrate @ 7083]
Herman Bloggs <herman@bluedigits.com>
parents:
5336
diff
changeset
|
88 | lastTime = setup_shared_mem(); |
| 9418 | 89 | |
|
6561
88ff258f78dd
[gaim-migrate @ 7083]
Herman Bloggs <herman@bluedigits.com>
parents:
5336
diff
changeset
|
90 | if (lastTime) |
|
88ff258f78dd
[gaim-migrate @ 7083]
Herman Bloggs <herman@bluedigits.com>
parents:
5336
diff
changeset
|
91 | *lastTime = GetTickCount(); |
|
88ff258f78dd
[gaim-migrate @ 7083]
Herman Bloggs <herman@bluedigits.com>
parents:
5336
diff
changeset
|
92 | } |
| 5336 | 93 | return CallNextHookEx(keyHook, code, wParam, lParam); |
| 4533 | 94 | } |
| 95 | ||
| 96 | ||
| 97 | LRESULT CALLBACK MouseProc(int code, WPARAM wParam, LPARAM lParam) { | |
|
4548
f89a7e6e9508
[gaim-migrate @ 4827]
Herman Bloggs <herman@bluedigits.com>
parents:
4533
diff
changeset
|
98 | /* We need to verify that the Mouse pointer has actually moved. */ |
|
6561
88ff258f78dd
[gaim-migrate @ 7083]
Herman Bloggs <herman@bluedigits.com>
parents:
5336
diff
changeset
|
99 | if(!(code < 0) && |
|
88ff258f78dd
[gaim-migrate @ 7083]
Herman Bloggs <herman@bluedigits.com>
parents:
5336
diff
changeset
|
100 | !((g_point.x == ((MOUSEHOOKSTRUCT*)lParam)->pt.x) && |
|
88ff258f78dd
[gaim-migrate @ 7083]
Herman Bloggs <herman@bluedigits.com>
parents:
5336
diff
changeset
|
101 | (g_point.y == ((MOUSEHOOKSTRUCT*)lParam)->pt.y))) { |
|
88ff258f78dd
[gaim-migrate @ 7083]
Herman Bloggs <herman@bluedigits.com>
parents:
5336
diff
changeset
|
102 | g_point.x = ((MOUSEHOOKSTRUCT*)lParam)->pt.x; |
|
88ff258f78dd
[gaim-migrate @ 7083]
Herman Bloggs <herman@bluedigits.com>
parents:
5336
diff
changeset
|
103 | g_point.y = ((MOUSEHOOKSTRUCT*)lParam)->pt.y; |
| 9418 | 104 | |
|
6561
88ff258f78dd
[gaim-migrate @ 7083]
Herman Bloggs <herman@bluedigits.com>
parents:
5336
diff
changeset
|
105 | if (lastTime == NULL) |
|
88ff258f78dd
[gaim-migrate @ 7083]
Herman Bloggs <herman@bluedigits.com>
parents:
5336
diff
changeset
|
106 | lastTime = setup_shared_mem(); |
| 9418 | 107 | |
|
6561
88ff258f78dd
[gaim-migrate @ 7083]
Herman Bloggs <herman@bluedigits.com>
parents:
5336
diff
changeset
|
108 | if (lastTime) |
|
88ff258f78dd
[gaim-migrate @ 7083]
Herman Bloggs <herman@bluedigits.com>
parents:
5336
diff
changeset
|
109 | *lastTime = GetTickCount(); |
|
88ff258f78dd
[gaim-migrate @ 7083]
Herman Bloggs <herman@bluedigits.com>
parents:
5336
diff
changeset
|
110 | } |
| 5336 | 111 | return CallNextHookEx(mouseHook, code, wParam, lParam); |
| 4533 | 112 | } |
| 113 | ||
| 114 | ||
| 115 | EXPORT DWORD wgaim_get_lastactive() { | |
| 9417 | 116 | DWORD result = 0; |
| 9418 | 117 | |
| 118 | /* If we have GetLastInputInfo then use it, otherwise use the hooks*/ | |
| 9417 | 119 | if (g_GetLastInputInfo != NULL) { |
| 120 | LASTINPUTINFO lii; | |
| 121 | memset(&lii, 0, sizeof(lii)); | |
| 122 | lii.cbSize = sizeof(lii); | |
| 123 | if (g_GetLastInputInfo(&lii)) { | |
| 124 | result = lii.dwTime; | |
| 125 | } | |
| 126 | } else { | |
| 127 | if (lastTime == NULL) | |
| 128 | lastTime = setup_shared_mem(); | |
| 9418 | 129 | |
| 9417 | 130 | if (lastTime) |
| 131 | result = *lastTime; | |
| 132 | } | |
| 9418 | 133 | |
| 9417 | 134 | return result; |
| 4533 | 135 | } |
| 136 | ||
| 137 | ||
| 138 | EXPORT BOOL wgaim_set_idlehooks() { | |
| 9418 | 139 | /* Is GetLastInputInfo available?*/ |
| 9417 | 140 | g_user32 = LoadLibrary("user32.dll"); |
| 141 | if (g_user32) { | |
| 142 | g_GetLastInputInfo = (GETLASTINPUTINFO)GetProcAddress(g_user32, "GetLastInputInfo"); | |
| 143 | } | |
| 144 | ||
| 9418 | 145 | /* If we couldn't find GetLastInputInfo then fall back onto the hooking scheme*/ |
| 9417 | 146 | if (g_GetLastInputInfo == NULL) { |
| 9418 | 147 | /* Set up the shared memory.*/ |
| 9417 | 148 | lastTime = setup_shared_mem(); |
| 149 | if (lastTime == NULL) | |
| 150 | return FALSE; | |
| 151 | *lastTime = GetTickCount(); | |
| 9418 | 152 | |
| 153 | /* Set up the keyboard hook.*/ | |
| 9417 | 154 | keyHook = SetWindowsHookEx(WH_KEYBOARD, KeyboardProc, g_hInstance, 0); |
| 155 | if (keyHook == NULL) { | |
| 156 | UnmapViewOfFile(lastTime); | |
| 157 | CloseHandle(hMapObject); | |
| 158 | return FALSE; | |
| 159 | } | |
| 9418 | 160 | |
| 161 | /* Set up the mouse hook.*/ | |
| 9417 | 162 | mouseHook = SetWindowsHookEx(WH_MOUSE, MouseProc, g_hInstance, 0); |
| 163 | if (mouseHook == NULL) { | |
| 164 | UnhookWindowsHookEx(keyHook); | |
| 165 | UnmapViewOfFile(lastTime); | |
| 166 | CloseHandle(hMapObject); | |
| 167 | return FALSE; | |
| 168 | } | |
| 4533 | 169 | } |
| 9418 | 170 | |
| 4533 | 171 | return TRUE; |
| 172 | } | |
| 173 | ||
| 174 | ||
| 175 | EXPORT void wgaim_remove_idlehooks() { | |
| 9417 | 176 | if (g_user32 != NULL) |
| 177 | FreeLibrary(g_user32); | |
| 4533 | 178 | if (keyHook) |
| 179 | UnhookWindowsHookEx(keyHook); | |
| 180 | if (mouseHook) | |
| 181 | UnhookWindowsHookEx(mouseHook); | |
| 182 | if (lastTime) | |
| 183 | UnmapViewOfFile(lastTime); | |
| 184 | if (hMapObject) | |
| 185 | CloseHandle(hMapObject); | |
| 186 | } | |
| 187 | ||
| 188 | int WINAPI DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID lpReserved) { | |
| 189 | switch(dwReason) { | |
| 190 | case DLL_PROCESS_ATTACH: | |
| 191 | g_hInstance = hInstance; | |
|
4548
f89a7e6e9508
[gaim-migrate @ 4827]
Herman Bloggs <herman@bluedigits.com>
parents:
4533
diff
changeset
|
192 | g_point.x = 0; |
|
f89a7e6e9508
[gaim-migrate @ 4827]
Herman Bloggs <herman@bluedigits.com>
parents:
4533
diff
changeset
|
193 | g_point.y = 0; |
| 4533 | 194 | break; |
| 195 | case DLL_PROCESS_DETACH: | |
| 196 | break; | |
| 197 | } | |
| 198 | return TRUE; | |
| 199 | } |