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

Annotation of /trunk/PTD/PTD.cpp

Parent Directory Parent Directory | Revision Log Revision Log


Revision 412 - (hide 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 werner 46 /* PTD.cpp - Privacy Tray Dynamic
2 twoaday 412 * Copyright (C) 2002-2009, 2012 Timo Schulz
3 werner 46 *
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 twoaday 412 /* Reference to the DLL module handle */
24 werner 46 HINSTANCE glob_hinst;
25    
26 werner 61 /* We need a special section in the DLL for storing our shared data.
27 twoaday 261 This shared data is required by the hook function because that
28 werner 61 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 werner 46 #pragma data_seg(".SHARDAT")
36 werner 61 #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 werner 46 #pragma data_seg()
46 werner 61 #endif
47     #undef ATTR_SEC
48 werner 46
49 twoaday 412 /* Static variables that are used to record and replay key strokes */
50 werner 46 static unsigned *journ_keys = 0;
51 twoaday 305 static unsigned keyidx = 0;
52 werner 46 static unsigned nkeys = 0;
53 twoaday 273 static HHOOK journ_hook = NULL; /* Journaling hook handle. */
54 werner 46
55    
56 twoaday 412 /* Callback function for the Computer Based Training (CBT) hook */
57 werner 46 static LRESULT CALLBACK
58     PTD_CBT_proc (int code, WPARAM wparam, LPARAM lparam)
59     {
60 twoaday 412 HWND curr_hwnd;
61     DWORD proc_id;
62 werner 46
63     if (code >= 0 && code == HCBT_SETFOCUS) {
64     /* A window is about to receive the keyboard focus */
65    
66 twoaday 412 proc_id = 0;
67 werner 46 curr_hwnd = (HWND)wparam;
68 twoaday 273 GetWindowThreadProcessId (curr_hwnd, &proc_id);
69 werner 46 /* 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 twoaday 412 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 werner 46 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 twoaday 334 PTD_get_current_window (void)
90 werner 46 {
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 twoaday 412 * based training hook, more precisely the HCBT_SETFOCUS to find out the
108 werner 46 * 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 twoaday 334
122     // FIXME: I doubt this is working for Windows 7
123 werner 46 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 twoaday 305 /*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 werner 46
133     return TRUE;
134     }
135    
136    
137     /* Remove the CTB hook from the system and reset all variables. */
138     extern "C" void
139 twoaday 334 PTD_delete_hook (void)
140 werner 46 {
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 twoaday 334 PTD_is_hook_used (void)
153 werner 46 {
154     return shell_traywnd && cbt_hook;
155     }
156    
157 twoaday 334 /* 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 werner 46 static LRESULT CALLBACK
164     PTD_playback_proc (int code, WPARAM wparam, LPARAM lparam)
165     {
166     LPEVENTMSG em;
167    
168     if (code == HC_SKIP) {
169 twoaday 305 keyidx++;
170 twoaday 334 if (keyidx >= nkeys) {
171 werner 46 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 twoaday 305 if (journ_keys[keyidx] & 0x8000)
184     em->message = journ_keys[keyidx] & 0x4000 ? WM_SYSKEYDOWN : WM_KEYDOWN;
185 werner 46 else
186 twoaday 305 em->message = journ_keys[keyidx] & 0x4000 ? WM_SYSKEYUP : WM_KEYUP;
187 twoaday 334 em->paramL = LOBYTE (journ_keys[keyidx])
188 twoaday 305 | (MapVirtualKey (LOBYTE (journ_keys[keyidx]), 0) << 8);
189 werner 46 em->paramH = 1;
190     em->time = GetTickCount ();
191     return 0;
192     }
193    
194     return CallNextHookEx (journ_hook, code, wparam, lparam);
195 twoaday 248 }
196 werner 46
197    
198    
199     extern "C" BOOL
200 twoaday 334 PTD_keyboard_send_keys (UINT *keys, UINT n_keys)
201 werner 46 {
202     MSG msg;
203     journ_keys = keys;
204 twoaday 305 keyidx = 0;
205 twoaday 334 nkeys = n_keys;
206 werner 46
207 twoaday 334 /* Return immediately if there is an active hook */
208 werner 46 if (journ_hook)
209     return FALSE;
210    
211 twoaday 334 while (GetAsyncKeyState (VK_MENU) & 0x8000 ||
212     GetAsyncKeyState (VK_SHIFT) & 0x8000 ||
213     GetAsyncKeyState (VK_CONTROL) & 0x8000) {
214 werner 46 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 twoaday 334 /* Main entry point for the DLL */
246 twoaday 248 extern "C" BOOL WINAPI
247 werner 46 DllMain (HINSTANCE hinst, DWORD reason, LPVOID reserv)
248     {
249     switch (reason) {
250 twoaday 334 case DLL_PROCESS_ATTACH:
251 twoaday 325 glob_hinst = hinst;
252 werner 46 break;
253 twoaday 325
254     case DLL_PROCESS_DETACH:
255     break;
256    
257 werner 46 case DLL_THREAD_ATTACH:
258     case DLL_THREAD_DETACH:
259     break;
260 twoaday 325
261 werner 46 }
262 twoaday 325
263 werner 46 return TRUE;
264     }

Properties

Name Value
svn:eol-style native

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26