/[winpt]/trunk/PTD/PTD.cpp
ViewVC logotype

Contents of /trunk/PTD/PTD.cpp

Parent Directory Parent Directory | Revision Log Revision Log


Revision 412 - (show annotations)
Sat Feb 11 15:03:43 2012 UTC (13 years ago) by twoaday
File size: 8121 byte(s)
2012-02-11  Timo Schulz  <twoaday@gmx.net>

        * PTD.cpp (PTD_CBT_proc): Additional comments and
	style cleanups.
		

1 /* PTD.cpp - Privacy Tray Dynamic
2 * Copyright (C) 2002-2009, 2012 Timo Schulz
3 *
4 * This file is part of WinPT.
5 *
6 * WinPT is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * WinPT is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 */
16 #ifdef HAVE_CONFIG_H
17 #include <config.h>
18 #endif
19
20 #include <windows.h>
21 #include <stdio.h>
22
23 /* Reference to the DLL module handle */
24 HINSTANCE glob_hinst;
25
26 /* We need a special section in the DLL for storing our shared data.
27 This shared data is required by the hook function because that
28 function is called in the context of the actual thread running the
29 hook and thus we need a way to communicate the result of our hook
30 function back to us. We use a shared data segment for this. */
31 #ifdef __GNUC__
32 #define ATTR_SEC __attribute__((section (".SHARDAT"), shared))
33 #else
34 #define ATTR_SEC
35 #pragma data_seg(".SHARDAT")
36 #endif
37 static HHOOK cbt_hook ATTR_SEC = NULL; /* CTB hook handle. */
38 static DWORD tray_proc_id ATTR_SEC = 0; /* WinPT PID */
39 static HWND shell_traywnd ATTR_SEC = 0; /* Tray window handle. */
40 static HWND curr_focus ATTR_SEC = NULL; /* Current window focus handle. */
41 static HWND rebar_w32 ATTR_SEC = NULL;
42 static HWND mstask_swc ATTR_SEC = NULL;
43 static HWND systab_c32 ATTR_SEC = NULL;
44 #ifndef __GNUC__
45 #pragma data_seg()
46 #endif
47 #undef ATTR_SEC
48
49 /* Static variables that are used to record and replay key strokes */
50 static unsigned *journ_keys = 0;
51 static unsigned keyidx = 0;
52 static unsigned nkeys = 0;
53 static HHOOK journ_hook = NULL; /* Journaling hook handle. */
54
55
56 /* Callback function for the Computer Based Training (CBT) hook */
57 static LRESULT CALLBACK
58 PTD_CBT_proc (int code, WPARAM wparam, LPARAM lparam)
59 {
60 HWND curr_hwnd;
61 DWORD proc_id;
62
63 if (code >= 0 && code == HCBT_SETFOCUS) {
64 /* A window is about to receive the keyboard focus */
65
66 proc_id = 0;
67 curr_hwnd = (HWND)wparam;
68 GetWindowThreadProcessId (curr_hwnd, &proc_id);
69 /* Only if the current window is different from this window list,
70 we set the new focus. For more information read the hint in
71 PTD_initialize. */
72 if ((proc_id != tray_proc_id) &&
73 (curr_hwnd != NULL) &&
74 (curr_hwnd != curr_focus) &&
75 (curr_hwnd != shell_traywnd) &&
76 (curr_hwnd != systab_c32) &&
77 (curr_hwnd != mstask_swc) &&
78 (curr_hwnd != rebar_w32)) {
79 curr_focus = curr_hwnd;
80 }
81 }
82
83 return CallNextHookEx (cbt_hook , code, wparam, lparam);
84 }
85
86
87 /* Return the last selected window */
88 extern "C" HWND
89 PTD_get_current_window (void)
90 {
91 return curr_focus;
92 }
93
94
95 /* Initialize CTB hook and try to find the system windows. */
96 extern "C" BOOL
97 PTD_initialize (void)
98 {
99 tray_proc_id = GetCurrentProcessId ();
100 cbt_hook = SetWindowsHookEx (WH_CBT, PTD_CBT_proc, glob_hinst, 0);
101 if (cbt_hook == NULL)
102 return FALSE;
103
104 /* Okay, what are we doing here:
105 * In the past I used the Spy++ application to find out why the old current
106 * window doesn't work on so much systems. Now we try to use the computer
107 * based training hook, more precisely the HCBT_SETFOCUS to find out the
108 * last window focus. But to succeed we need to ignore some windows
109 * because otherwise our own window or a window from the taskbar
110 * would be recognized.
111 *
112 * Here is what the Spy++ says about the windows order:
113 * Shell_TrayWnd
114 * \ ReBarWindow32
115 * \ MSTaskSwWClass
116 * \ SysTabControl32
117 *
118 * As a result we need to ignore those windows to prevent failured
119 * in the code.
120 */
121
122 // FIXME: I doubt this is working for Windows 7
123 shell_traywnd = FindWindowEx (NULL, NULL, "Shell_TrayWnd", NULL);
124 rebar_w32 = FindWindowEx (shell_traywnd, NULL, "ReBarWindow32", NULL);
125 mstask_swc = FindWindowEx (rebar_w32, NULL, "MSTaskSwWClass", NULL);
126 systab_c32 = FindWindowEx (mstask_swc, NULL, "SysTabControl32", NULL);
127
128 /*debug ("tray_proc_id=%u cbt_hook=%p shell_traywnd=%p rebar_w32=%p "
129 "mstask_swc=%p systab_c32=%p",
130 tray_proc_id, cbt_hook, shell_traywnd, rebar_w32,
131 mstask_swc, systab_c32);*/
132
133 return TRUE;
134 }
135
136
137 /* Remove the CTB hook from the system and reset all variables. */
138 extern "C" void
139 PTD_delete_hook (void)
140 {
141 if (!cbt_hook)
142 return;
143 UnhookWindowsHookEx (cbt_hook);
144 cbt_hook = NULL;
145 shell_traywnd = NULL;
146 tray_proc_id = 0;
147 }
148
149
150 /* Return if the CTB hook is currently used. */
151 extern "C" int
152 PTD_is_hook_used (void)
153 {
154 return shell_traywnd && cbt_hook;
155 }
156
157 /* From the MSDN:
158 * "Typically, an application uses this function to play back a series
159 * of mouse and keyboard messages recorded previously by the
160 * JournalRecordProc hook procedure. As long as a JournalPlaybackProc
161 * hook procedure is installed, regular mouse and keyboard input is disabled."
162 */
163 static LRESULT CALLBACK
164 PTD_playback_proc (int code, WPARAM wparam, LPARAM lparam)
165 {
166 LPEVENTMSG em;
167
168 if (code == HC_SKIP) {
169 keyidx++;
170 if (keyidx >= nkeys) {
171 UnhookWindowsHookEx (journ_hook);
172 journ_hook = NULL;
173 }
174 return 0;
175 }
176 else if (code == HC_GETNEXT) {
177 /* Here is an overview what the event message struct can contain:
178 * message - WM_KEYUP, WM_KEYDOWN, WM_SYSKEYUP, WM_SYSKEYDOWN:
179 * paramL - specifies the virtual key code of the key that was pressed.
180 * paramH - specifies the scan code.
181 */
182 em = (LPEVENTMSG )lparam;
183 if (journ_keys[keyidx] & 0x8000)
184 em->message = journ_keys[keyidx] & 0x4000 ? WM_SYSKEYDOWN : WM_KEYDOWN;
185 else
186 em->message = journ_keys[keyidx] & 0x4000 ? WM_SYSKEYUP : WM_KEYUP;
187 em->paramL = LOBYTE (journ_keys[keyidx])
188 | (MapVirtualKey (LOBYTE (journ_keys[keyidx]), 0) << 8);
189 em->paramH = 1;
190 em->time = GetTickCount ();
191 return 0;
192 }
193
194 return CallNextHookEx (journ_hook, code, wparam, lparam);
195 }
196
197
198
199 extern "C" BOOL
200 PTD_keyboard_send_keys (UINT *keys, UINT n_keys)
201 {
202 MSG msg;
203 journ_keys = keys;
204 keyidx = 0;
205 nkeys = n_keys;
206
207 /* Return immediately if there is an active hook */
208 if (journ_hook)
209 return FALSE;
210
211 while (GetAsyncKeyState (VK_MENU) & 0x8000 ||
212 GetAsyncKeyState (VK_SHIFT) & 0x8000 ||
213 GetAsyncKeyState (VK_CONTROL) & 0x8000) {
214 if (PeekMessage (&msg, NULL, 0, 0, PM_REMOVE)) {
215 if (msg.message == WM_QUIT) {
216 PostMessage (msg.hwnd, msg.message, msg.wParam, msg.lParam);
217 return FALSE;
218 }
219 TranslateMessage (&msg);
220 DispatchMessage (&msg);
221 }
222 }
223 journ_hook = SetWindowsHookEx (WH_JOURNALPLAYBACK,
224 (HOOKPROC)PTD_playback_proc,
225 glob_hinst, 0);
226 if (journ_hook == NULL)
227 return FALSE;
228
229 while (journ_hook) {
230 if (PeekMessage (&msg, NULL, 0, 0, PM_REMOVE)) {
231 if (msg.message == WM_QUIT) {
232 if (journ_hook)
233 UnhookWindowsHookEx (journ_hook);
234 PostMessage (msg.hwnd, msg.message, msg.wParam, msg.wParam);
235 }
236 TranslateMessage (&msg);
237 DispatchMessage (&msg);
238 }
239 }
240
241 return TRUE;
242 }
243
244
245 /* Main entry point for the DLL */
246 extern "C" BOOL WINAPI
247 DllMain (HINSTANCE hinst, DWORD reason, LPVOID reserv)
248 {
249 switch (reason) {
250 case DLL_PROCESS_ATTACH:
251 glob_hinst = hinst;
252 break;
253
254 case DLL_PROCESS_DETACH:
255 break;
256
257 case DLL_THREAD_ATTACH:
258 case DLL_THREAD_DETACH:
259 break;
260
261 }
262
263 return TRUE;
264 }

Properties

Name Value
svn:eol-style native

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26