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

Contents of /trunk/PTD/PTD.cpp

Parent Directory Parent Directory | Revision Log Revision Log


Revision 413 - (show annotations)
Sat Feb 11 16:33:43 2012 UTC (13 years ago) by twoaday
File size: 7912 byte(s)


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 return TRUE;
129 }
130
131
132 /* Remove the CTB hook from the system and reset all variables. */
133 extern "C" void
134 PTD_delete_hook (void)
135 {
136 if (!cbt_hook)
137 return;
138 UnhookWindowsHookEx (cbt_hook);
139 cbt_hook = NULL;
140 shell_traywnd = NULL;
141 tray_proc_id = 0;
142 }
143
144
145 /* Return if the CTB hook is currently used. */
146 extern "C" int
147 PTD_is_hook_used (void)
148 {
149 return shell_traywnd && cbt_hook;
150 }
151
152 /* From the MSDN:
153 * "Typically, an application uses this function to play back a series
154 * of mouse and keyboard messages recorded previously by the
155 * JournalRecordProc hook procedure. As long as a JournalPlaybackProc
156 * hook procedure is installed, regular mouse and keyboard input is disabled."
157 */
158 static LRESULT CALLBACK
159 PTD_playback_proc (int code, WPARAM wparam, LPARAM lparam)
160 {
161 LPEVENTMSG em;
162
163 if (code == HC_SKIP) {
164 keyidx++;
165 if (keyidx >= nkeys) {
166 UnhookWindowsHookEx (journ_hook);
167 journ_hook = NULL;
168 }
169 return 0;
170 }
171 else if (code == HC_GETNEXT) {
172 /* Here is an overview what the event message struct can contain:
173 * message - WM_KEYUP, WM_KEYDOWN, WM_SYSKEYUP, WM_SYSKEYDOWN:
174 * paramL - specifies the virtual key code of the key that was pressed.
175 * paramH - specifies the scan code.
176 */
177 em = (LPEVENTMSG )lparam;
178 if (journ_keys[keyidx] & 0x8000)
179 em->message = journ_keys[keyidx] & 0x4000 ? WM_SYSKEYDOWN : WM_KEYDOWN;
180 else
181 em->message = journ_keys[keyidx] & 0x4000 ? WM_SYSKEYUP : WM_KEYUP;
182 em->paramL = LOBYTE (journ_keys[keyidx])
183 | (MapVirtualKey (LOBYTE (journ_keys[keyidx]), 0) << 8);
184 em->paramH = 1;
185 em->time = GetTickCount ();
186 return 0;
187 }
188
189 return CallNextHookEx (journ_hook, code, wparam, lparam);
190 }
191
192
193
194 extern "C" BOOL
195 PTD_keyboard_send_keys (UINT *keys, UINT n_keys)
196 {
197 MSG msg;
198 journ_keys = keys;
199 keyidx = 0;
200 nkeys = n_keys;
201
202 /* Return immediately if there is an active hook */
203 if (journ_hook)
204 return FALSE;
205
206 while (GetAsyncKeyState (VK_MENU) & 0x8000 ||
207 GetAsyncKeyState (VK_SHIFT) & 0x8000 ||
208 GetAsyncKeyState (VK_CONTROL) & 0x8000) {
209 if (PeekMessage (&msg, NULL, 0, 0, PM_REMOVE)) {
210 if (msg.message == WM_QUIT) {
211 PostMessage (msg.hwnd, msg.message, msg.wParam, msg.lParam);
212 return FALSE;
213 }
214 TranslateMessage (&msg);
215 DispatchMessage (&msg);
216 }
217 }
218 journ_hook = SetWindowsHookEx (WH_JOURNALPLAYBACK,
219 (HOOKPROC)PTD_playback_proc,
220 glob_hinst, 0);
221 if (journ_hook == NULL)
222 return FALSE;
223
224 while (journ_hook) {
225 if (PeekMessage (&msg, NULL, 0, 0, PM_REMOVE)) {
226 if (msg.message == WM_QUIT) {
227 if (journ_hook)
228 UnhookWindowsHookEx (journ_hook);
229 PostMessage (msg.hwnd, msg.message, msg.wParam, msg.wParam);
230 }
231 TranslateMessage (&msg);
232 DispatchMessage (&msg);
233 }
234 }
235
236 return TRUE;
237 }
238
239
240 /* Main entry point for the DLL */
241 extern "C" BOOL WINAPI
242 DllMain (HINSTANCE hinst, DWORD reason, LPVOID reserv)
243 {
244 switch (reason) {
245 case DLL_PROCESS_ATTACH:
246 glob_hinst = hinst;
247 break;
248
249 case DLL_PROCESS_DETACH:
250 break;
251
252 case DLL_THREAD_ATTACH:
253 case DLL_THREAD_DETACH:
254 break;
255
256 }
257
258 return TRUE;
259 }

Properties

Name Value
svn:eol-style native

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26