/[winpt]/trunk/Src/wptSafeEditCtrl.cpp
ViewVC logotype

Annotation of /trunk/Src/wptSafeEditCtrl.cpp

Parent Directory Parent Directory | Revision Log Revision Log


Revision 328 - (hide annotations)
Fri Sep 25 16:07:38 2009 UTC (15 years, 5 months ago) by twoaday
File size: 6214 byte(s)


1 twoaday 181 /* wptSafeEditCtrl.cpp - Safe edit control for passwords
2 twoaday 328 * Copyright (C) 2006, 2009 Timo Schulz
3     * Copyright (C) 2006 g10 Code GmbH
4 twoaday 181 *
5     * This file is part of WinPT.
6     *
7     * WinPT is free software; you can redistribute it and/or modify
8     * it under the terms of the GNU General Public License as published by
9     * the Free Software Foundation; either version 2 of the License, or
10     * (at your option) any later version.
11     *
12     * WinPT is distributed in the hope that it will be useful,
13     * but WITHOUT ANY WARRANTY; without even the implied warranty of
14     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15     * GNU General Public License for more details.
16     */
17 twoaday 271 #ifdef HAVE_CONFIG_H
18     #include <config.h>
19     #endif
20 twoaday 181
21     #include <windows.h>
22     #include <stdio.h>
23     #include <richedit.h>
24     #include "resource.h"
25    
26     #include "wptTypes.h"
27     #include "wptW32API.h"
28    
29     /* New message to retrieve text. */
30     #define WM_SAFE_GETTEXT (WM_USER+11)
31    
32     /* Hook context. */
33     struct hook_ctx_s {
34     HHOOK keyb; /* handle for the keyboard. */
35     HHOOK cbt; /* handle for computer based training (CBT) */
36     };
37     typedef struct hook_ctx_s *hook_ctx_t;
38    
39     /* Subclassing context. */
40     struct subclass_ctx_s {
41     WNDPROC new_wnd_fnc; /* old window procedure. */
42     WNDPROC old_wnd_fnc; /* new window procedure. */
43     HWND wnd; /* window handle that is subclassed. */
44     void *opaque;
45     };
46     typedef struct subclass_ctx_s *subclass_ctx_t;
47    
48    
49     /* Dummy hook procedure to avoid channing. */
50     static LRESULT CALLBACK
51     dummy_hook_proc (int code, WPARAM wparam, LPARAM lparam)
52     {
53     return FALSE;
54     }
55    
56    
57     /* Set dummy hooks to prevent that the control is monitored
58     by some external hook functions. */
59     static hook_ctx_t
60     install_dummy_hooks (void)
61     {
62     hook_ctx_t hc;
63    
64     hc = (hook_ctx_t)calloc (1, sizeof *hc);
65     if (!hc)
66     return NULL;
67     hc->cbt = SetWindowsHookEx (WH_CBT, dummy_hook_proc,
68     GetModuleHandle (NULL), 0);
69     if (hc->cbt == NULL) {
70     free (hc);
71     return NULL;
72     }
73     hc->keyb = SetWindowsHookEx (WH_KEYBOARD, dummy_hook_proc,
74     GetModuleHandle (NULL), 0);
75     if (hc->keyb == NULL) {
76     free (hc);
77     return NULL;
78     }
79     return hc;
80     }
81    
82    
83     /* Remove dummy hooks and free memory. */
84     static void
85     deinstall_dummy_hooks (hook_ctx_t hc)
86     {
87     UnhookWindowsHookEx (hc->cbt);
88     UnhookWindowsHookEx (hc->keyb);
89     free (hc);
90     }
91    
92    
93     /* Filtered window procedure for the passphrase edit control. */
94     static LRESULT CALLBACK
95     safe_edit_dlg_proc (HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam)
96     {
97     static subclass_ctx_t ctx = NULL;
98    
99     /* XXX: filter all messages which were not send from
100     the current process. */
101    
102     if (ctx == NULL)
103     ctx = (subclass_ctx_t)GetWindowLong (hwnd, GWL_USERDATA);
104    
105     switch (msg) {
106     case WM_CUT:
107     case WM_COPY:
108 twoaday 328 // TS: a lot of user asked if we could not allow pasting again.
109     //case WM_PASTE:
110 twoaday 181 /* do not allow to copy or paste the inserted text. */
111     return TRUE;
112    
113     case WM_KEYUP:
114     case WM_KEYDOWN:
115     /* XXX: maybe in a future release, we might want to provide
116     our own buffer implementation. */
117    
118     /* ignore 'end' and 'home' to make text selection more difficult. */
119     if ((int)wparam == VK_END || (int)wparam == VK_HOME)
120     return TRUE;
121     break;
122    
123     case WM_GETTEXT:
124     /* disallow normal gettext message. */
125     return TRUE;
126    
127     case WM_SAFE_GETTEXT:
128     { /* transform WM_GETTEXT request into EM_GETLINE request. */
129     char *buffer = (char*)wparam;
130     int n;
131     buffer[0] = (char)lparam;
132     n = SendMessage (hwnd, EM_GETLINE, 0, wparam);
133     buffer[n] = 0;
134     }
135     break;
136    
137     case EM_GETLINE:
138     break;
139    
140     case WM_LBUTTONDBLCLK:
141     case WM_RBUTTONUP:
142     case WM_RBUTTONDOWN:
143     /* prevent that the popup menu is displayed. */
144     return TRUE;
145    
146     case EM_SETSEL:
147     case EM_SCROLLCARET:
148     case EM_FINDTEXT:
149     case EM_FINDTEXTEX:
150     case EM_GETSELTEXT:
151     case EM_PASTESPECIAL:
152     case EM_GETTEXTRANGE:
153     case EM_STREAMIN:
154     case EM_STREAMOUT:
155     /* disallow message which could be used to copy the text. */
156     return TRUE;
157     }
158    
159     return CallWindowProc (ctx->old_wnd_fnc, hwnd, msg, wparam, lparam);
160     }
161    
162    
163     /* Sublclass the window in the dialog @dlg with the id @ctrlid.
164     @new_wnd_fnc is the new window procedure. */
165     static int
166     subclass_window (HWND dlg, int ctrlid, WNDPROC new_wnd_fnc,
167     subclass_ctx_t *r_ctx)
168     {
169     subclass_ctx_t ctx;
170    
171     *r_ctx = NULL;
172     ctx = (subclass_ctx_t)calloc (1, sizeof *ctx);
173     if (!ctx)
174     return -1;
175     ctx->wnd = GetDlgItem (dlg, ctrlid);
176     ctx->new_wnd_fnc = new_wnd_fnc;
177     ctx->old_wnd_fnc = (WNDPROC)GetWindowLong (ctx->wnd, GWL_WNDPROC);
178     if (!ctx->old_wnd_fnc) {
179     free (ctx);
180     return -1;
181     }
182     SetLastError (0);
183     SetWindowLong (ctx->wnd, GWL_WNDPROC, (LONG)new_wnd_fnc);
184     if (GetLastError () != 0) {
185     free (ctx);
186     return -1;
187     }
188     SetLastError (0);
189     SetWindowLong (ctx->wnd, GWL_USERDATA, (LONG)ctx);
190     if (GetLastError () != 0) {
191     free (ctx);
192     return -1;
193     }
194     if (r_ctx)
195     *r_ctx = ctx;
196     return 0;
197     }
198    
199    
200     /* Restore the old window procedure for the subclassed control
201     and free the memory. */
202     static void
203     subclass_free_memory (HWND dlg, int ctrlid)
204     {
205     subclass_ctx_t ctx;
206     HWND wnd;
207    
208     wnd = GetDlgItem (dlg, ctrlid);
209     ctx = (subclass_ctx_t)GetWindowLong (wnd, GWL_USERDATA);
210     SetWindowLong (ctx->wnd, GWL_WNDPROC, (LONG)ctx->old_wnd_fnc);
211     if (ctx != NULL)
212     free (ctx);
213     }
214    
215    
216     /* Init subclassing to provide a safer edit control
217     for the dialog @dlg control @ctlid. */
218     void
219     safe_edit_control_init (HWND dlg, int ctlid)
220     {
221     subclass_ctx_t ctx;
222    
223     subclass_window (dlg, ctlid, safe_edit_dlg_proc, &ctx);
224     if (ctx != NULL)
225     ctx->opaque = install_dummy_hooks ();
226     }
227    
228    
229     /* Reset subclassing for the edit control @ctlid. */
230     void
231     safe_edit_control_free (HWND dlg, int ctlid)
232     {
233     subclass_ctx_t ctx;
234     HWND wnd;
235    
236     wnd = GetDlgItem (dlg, ctlid);
237     ctx = (subclass_ctx_t)GetWindowLong (wnd, GWL_USERDATA);
238     if (ctx != NULL && ctx->opaque != NULL)
239     deinstall_dummy_hooks ((hook_ctx_t)ctx->opaque);
240     subclass_free_memory (dlg, ctlid);
241     }
242    
243    
244     UINT
245     SafeGetDlgItemText (HWND dlg, int id, char *buf, int buflen)
246     {
247 twoaday 193 memset (buf, 0, buflen);
248 twoaday 181 SendDlgItemMessage (dlg, id, WM_SAFE_GETTEXT, (WPARAM)buf, (LPARAM)buflen);
249     return strlen (buf);
250     }

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26