2006-04-23 18:26:03 +00:00
|
|
|
/*
|
|
|
|
* windlg.c - dialogs for PuTTY(tel), including the configuration dialog.
|
|
|
|
*/
|
|
|
|
|
1999-01-08 13:02:13 +00:00
|
|
|
#include <stdio.h>
|
|
|
|
#include <stdlib.h>
|
2003-03-05 22:07:40 +00:00
|
|
|
#include <limits.h>
|
|
|
|
#include <assert.h>
|
2001-02-05 13:04:00 +00:00
|
|
|
#include <ctype.h>
|
2001-02-27 17:02:51 +00:00
|
|
|
#include <time.h>
|
1999-01-08 13:02:13 +00:00
|
|
|
|
1999-07-06 19:42:57 +00:00
|
|
|
#include "putty.h"
|
2003-10-12 13:46:12 +00:00
|
|
|
#include "ssh.h"
|
1999-01-08 13:02:13 +00:00
|
|
|
#include "win_res.h"
|
2000-09-27 15:21:04 +00:00
|
|
|
#include "storage.h"
|
2003-03-05 22:07:40 +00:00
|
|
|
#include "dialog.h"
|
2015-12-22 12:43:31 +00:00
|
|
|
#include "licence.h"
|
1999-01-08 13:02:13 +00:00
|
|
|
|
2003-10-12 13:46:12 +00:00
|
|
|
#include <commctrl.h>
|
|
|
|
#include <commdlg.h>
|
2004-01-20 20:35:27 +00:00
|
|
|
#include <shellapi.h>
|
2003-10-12 13:46:12 +00:00
|
|
|
|
2002-01-08 09:45:10 +00:00
|
|
|
#ifdef MSVC4
|
|
|
|
#define TVINSERTSTRUCT TV_INSERTSTRUCT
|
|
|
|
#define TVITEM TV_ITEM
|
|
|
|
#define ICON_BIG 1
|
|
|
|
#endif
|
|
|
|
|
2003-03-05 22:07:40 +00:00
|
|
|
/*
|
|
|
|
* These are the various bits of data required to handle the
|
|
|
|
* portable-dialog stuff in the config box. Having them at file
|
|
|
|
* scope in here isn't too bad a place to put them; if we were ever
|
|
|
|
* to need more than one config box per process we could always
|
|
|
|
* shift them to a per-config-box structure stored in GWL_USERDATA.
|
|
|
|
*/
|
|
|
|
static struct controlbox *ctrlbox;
|
|
|
|
/*
|
|
|
|
* ctrls_base holds the OK and Cancel buttons: the controls which
|
|
|
|
* are present in all dialog panels. ctrls_panel holds the ones
|
|
|
|
* which change from panel to panel.
|
|
|
|
*/
|
|
|
|
static struct winctrls ctrls_base, ctrls_panel;
|
|
|
|
static struct dlgparam dp;
|
|
|
|
|
Don't grow logevent buf indefinitely
The PuTTY GUIs (Unix and Windows) maintain an in-memory event log
for display to users as they request. This uses ints for tracking
eventlog size, which is subject to memory exhaustion and (given
enough heap space) overflow attacks by servers (via, e.g., constant
rekeying).
Also a bounded log is more user-friendly. It is rare to want more
than the initial logging and the logging from a few recent rekey
events.
The Windows fix has been tested using Dr. Memory as a valgrind
substitute. No errors corresponding to the affected code showed up.
The Dr. Memory results.txt was split into a file per-error and then
grep Error $(grep -l windlg *)|cut -d: -f3-|sort |uniq -c
was used to compare. Differences arose from different usage of the GUI,
but no error could be traced to the code modified in this commit.
The Unix fix has been tested using valgrind. We don't destroy the
eventlog_stuff eventlog arrays, so we can't be entirely sure that we
don't leak more than we did before, but from code inspection it looks
like we don't (and anyways, if we leaked as much as before, just without
the integer overflow, well, that's still an improvement).
2013-07-22 23:09:04 +00:00
|
|
|
#define LOGEVENT_INITIAL_MAX 128
|
|
|
|
#define LOGEVENT_CIRCULAR_MAX 128
|
|
|
|
|
|
|
|
static char *events_initial[LOGEVENT_INITIAL_MAX];
|
|
|
|
static char *events_circular[LOGEVENT_CIRCULAR_MAX];
|
|
|
|
static int ninitial = 0, ncircular = 0, circular_first = 0;
|
1999-11-09 11:10:04 +00:00
|
|
|
|
Post-release destabilisation! Completely remove the struct type
'Config' in putty.h, which stores all PuTTY's settings and includes an
arbitrary length limit on every single one of those settings which is
stored in string form. In place of it is 'Conf', an opaque data type
everywhere outside the new file conf.c, which stores a list of (key,
value) pairs in which every key contains an integer identifying a
configuration setting, and for some of those integers the key also
contains extra parts (so that, for instance, CONF_environmt is a
string-to-string mapping). Everywhere that a Config was previously
used, a Conf is now; everywhere there was a Config structure copy,
conf_copy() is called; every lookup, adjustment, load and save
operation on a Config has been rewritten; and there's a mechanism for
serialising a Conf into a binary blob and back for use with Duplicate
Session.
User-visible effects of this change _should_ be minimal, though I
don't doubt I've introduced one or two bugs here and there which will
eventually be found. The _intended_ visible effects of this change are
that all arbitrary limits on configuration strings and lists (e.g.
limit on number of port forwardings) should now disappear; that list
boxes in the configuration will now be displayed in a sorted order
rather than the arbitrary order in which they were added to the list
(since the underlying data structure is now a sorted tree234 rather
than an ad-hoc comma-separated string); and one more specific change,
which is that local and dynamic port forwardings on the same port
number are now mutually exclusive in the configuration (putting 'D' in
the key rather than the value was a mistake in the first place).
One other reorganisation as a result of this is that I've moved all
the dialog.c standard handlers (dlg_stdeditbox_handler and friends)
out into config.c, because I can't really justify calling them generic
any more. When they took a pointer to an arbitrary structure type and
the offset of a field within that structure, they were independent of
whether that structure was a Config or something completely different,
but now they really do expect to talk to a Conf, which can _only_ be
used for PuTTY configuration, so I've renamed them all things like
conf_editbox_handler and moved them out of the nominally independent
dialog-box management module into the PuTTY-specific config.c.
[originally from svn r9214]
2011-07-14 18:52:21 +00:00
|
|
|
extern Conf *conf; /* defined in window.c */
|
2003-01-12 15:32:31 +00:00
|
|
|
|
2002-03-09 17:59:15 +00:00
|
|
|
#define PRINTER_DISABLED_STRING "None (printing disabled)"
|
|
|
|
|
2001-01-07 16:27:48 +00:00
|
|
|
void force_normal(HWND hwnd)
|
2000-07-26 12:13:51 +00:00
|
|
|
{
|
2000-10-06 13:21:36 +00:00
|
|
|
static int recurse = 0;
|
2000-07-26 12:13:51 +00:00
|
|
|
|
|
|
|
WINDOWPLACEMENT wp;
|
|
|
|
|
2001-05-06 14:35:20 +00:00
|
|
|
if (recurse)
|
|
|
|
return;
|
2000-07-26 12:13:51 +00:00
|
|
|
recurse = 1;
|
|
|
|
|
|
|
|
wp.length = sizeof(wp);
|
2001-05-06 14:35:20 +00:00
|
|
|
if (GetWindowPlacement(hwnd, &wp) && wp.showCmd == SW_SHOWMAXIMIZED) {
|
2000-07-26 12:13:51 +00:00
|
|
|
wp.showCmd = SW_SHOWNORMAL;
|
|
|
|
SetWindowPlacement(hwnd, &wp);
|
|
|
|
}
|
|
|
|
recurse = 0;
|
|
|
|
}
|
|
|
|
|
Don't grow logevent buf indefinitely
The PuTTY GUIs (Unix and Windows) maintain an in-memory event log
for display to users as they request. This uses ints for tracking
eventlog size, which is subject to memory exhaustion and (given
enough heap space) overflow attacks by servers (via, e.g., constant
rekeying).
Also a bounded log is more user-friendly. It is rare to want more
than the initial logging and the logging from a few recent rekey
events.
The Windows fix has been tested using Dr. Memory as a valgrind
substitute. No errors corresponding to the affected code showed up.
The Dr. Memory results.txt was split into a file per-error and then
grep Error $(grep -l windlg *)|cut -d: -f3-|sort |uniq -c
was used to compare. Differences arose from different usage of the GUI,
but no error could be traced to the code modified in this commit.
The Unix fix has been tested using valgrind. We don't destroy the
eventlog_stuff eventlog arrays, so we can't be entirely sure that we
don't leak more than we did before, but from code inspection it looks
like we don't (and anyways, if we leaked as much as before, just without
the integer overflow, well, that's still an improvement).
2013-07-22 23:09:04 +00:00
|
|
|
static char *getevent(int i)
|
|
|
|
{
|
|
|
|
if (i < ninitial)
|
|
|
|
return events_initial[i];
|
|
|
|
if ((i -= ninitial) < ncircular)
|
|
|
|
return events_circular[(circular_first + i) % LOGEVENT_CIRCULAR_MAX];
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2016-04-02 13:10:27 +00:00
|
|
|
static INT_PTR CALLBACK LogProc(HWND hwnd, UINT msg,
|
|
|
|
WPARAM wParam, LPARAM lParam)
|
2001-05-06 14:35:20 +00:00
|
|
|
{
|
1999-01-08 13:02:13 +00:00
|
|
|
int i;
|
|
|
|
|
|
|
|
switch (msg) {
|
|
|
|
case WM_INITDIALOG:
|
2003-04-06 14:11:33 +00:00
|
|
|
{
|
|
|
|
char *str = dupprintf("%s Event Log", appname);
|
|
|
|
SetWindowText(hwnd, str);
|
|
|
|
sfree(str);
|
|
|
|
}
|
2001-05-06 14:35:20 +00:00
|
|
|
{
|
|
|
|
static int tabs[4] = { 78, 108 };
|
|
|
|
SendDlgItemMessage(hwnd, IDN_LIST, LB_SETTABSTOPS, 2,
|
|
|
|
(LPARAM) tabs);
|
|
|
|
}
|
Don't grow logevent buf indefinitely
The PuTTY GUIs (Unix and Windows) maintain an in-memory event log
for display to users as they request. This uses ints for tracking
eventlog size, which is subject to memory exhaustion and (given
enough heap space) overflow attacks by servers (via, e.g., constant
rekeying).
Also a bounded log is more user-friendly. It is rare to want more
than the initial logging and the logging from a few recent rekey
events.
The Windows fix has been tested using Dr. Memory as a valgrind
substitute. No errors corresponding to the affected code showed up.
The Dr. Memory results.txt was split into a file per-error and then
grep Error $(grep -l windlg *)|cut -d: -f3-|sort |uniq -c
was used to compare. Differences arose from different usage of the GUI,
but no error could be traced to the code modified in this commit.
The Unix fix has been tested using valgrind. We don't destroy the
eventlog_stuff eventlog arrays, so we can't be entirely sure that we
don't leak more than we did before, but from code inspection it looks
like we don't (and anyways, if we leaked as much as before, just without
the integer overflow, well, that's still an improvement).
2013-07-22 23:09:04 +00:00
|
|
|
for (i = 0; i < ninitial; i++)
|
|
|
|
SendDlgItemMessage(hwnd, IDN_LIST, LB_ADDSTRING,
|
|
|
|
0, (LPARAM) events_initial[i]);
|
|
|
|
for (i = 0; i < ncircular; i++)
|
2001-05-06 14:35:20 +00:00
|
|
|
SendDlgItemMessage(hwnd, IDN_LIST, LB_ADDSTRING,
|
Don't grow logevent buf indefinitely
The PuTTY GUIs (Unix and Windows) maintain an in-memory event log
for display to users as they request. This uses ints for tracking
eventlog size, which is subject to memory exhaustion and (given
enough heap space) overflow attacks by servers (via, e.g., constant
rekeying).
Also a bounded log is more user-friendly. It is rare to want more
than the initial logging and the logging from a few recent rekey
events.
The Windows fix has been tested using Dr. Memory as a valgrind
substitute. No errors corresponding to the affected code showed up.
The Dr. Memory results.txt was split into a file per-error and then
grep Error $(grep -l windlg *)|cut -d: -f3-|sort |uniq -c
was used to compare. Differences arose from different usage of the GUI,
but no error could be traced to the code modified in this commit.
The Unix fix has been tested using valgrind. We don't destroy the
eventlog_stuff eventlog arrays, so we can't be entirely sure that we
don't leak more than we did before, but from code inspection it looks
like we don't (and anyways, if we leaked as much as before, just without
the integer overflow, well, that's still an improvement).
2013-07-22 23:09:04 +00:00
|
|
|
0, (LPARAM) events_circular[(circular_first + i) % LOGEVENT_CIRCULAR_MAX]);
|
1999-01-08 13:02:13 +00:00
|
|
|
return 1;
|
|
|
|
case WM_COMMAND:
|
|
|
|
switch (LOWORD(wParam)) {
|
|
|
|
case IDOK:
|
2001-01-23 17:37:52 +00:00
|
|
|
case IDCANCEL:
|
1999-01-08 13:02:13 +00:00
|
|
|
logbox = NULL;
|
2001-05-06 14:35:20 +00:00
|
|
|
SetActiveWindow(GetParent(hwnd));
|
|
|
|
DestroyWindow(hwnd);
|
1999-01-08 13:02:13 +00:00
|
|
|
return 0;
|
2001-05-06 14:35:20 +00:00
|
|
|
case IDN_COPY:
|
2000-09-22 14:46:26 +00:00
|
|
|
if (HIWORD(wParam) == BN_CLICKED ||
|
|
|
|
HIWORD(wParam) == BN_DOUBLECLICKED) {
|
2001-05-06 14:35:20 +00:00
|
|
|
int selcount;
|
|
|
|
int *selitems;
|
|
|
|
selcount = SendDlgItemMessage(hwnd, IDN_LIST,
|
|
|
|
LB_GETSELCOUNT, 0, 0);
|
|
|
|
if (selcount == 0) { /* don't even try to copy zero items */
|
|
|
|
MessageBeep(0);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2003-03-29 16:14:26 +00:00
|
|
|
selitems = snewn(selcount, int);
|
2001-05-06 14:35:20 +00:00
|
|
|
if (selitems) {
|
|
|
|
int count = SendDlgItemMessage(hwnd, IDN_LIST,
|
|
|
|
LB_GETSELITEMS,
|
|
|
|
selcount,
|
|
|
|
(LPARAM) selitems);
|
|
|
|
int i;
|
|
|
|
int size;
|
|
|
|
char *clipdata;
|
|
|
|
static unsigned char sel_nl[] = SEL_NL;
|
|
|
|
|
|
|
|
if (count == 0) { /* can't copy zero stuff */
|
|
|
|
MessageBeep(0);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
size = 0;
|
|
|
|
for (i = 0; i < count; i++)
|
|
|
|
size +=
|
Don't grow logevent buf indefinitely
The PuTTY GUIs (Unix and Windows) maintain an in-memory event log
for display to users as they request. This uses ints for tracking
eventlog size, which is subject to memory exhaustion and (given
enough heap space) overflow attacks by servers (via, e.g., constant
rekeying).
Also a bounded log is more user-friendly. It is rare to want more
than the initial logging and the logging from a few recent rekey
events.
The Windows fix has been tested using Dr. Memory as a valgrind
substitute. No errors corresponding to the affected code showed up.
The Dr. Memory results.txt was split into a file per-error and then
grep Error $(grep -l windlg *)|cut -d: -f3-|sort |uniq -c
was used to compare. Differences arose from different usage of the GUI,
but no error could be traced to the code modified in this commit.
The Unix fix has been tested using valgrind. We don't destroy the
eventlog_stuff eventlog arrays, so we can't be entirely sure that we
don't leak more than we did before, but from code inspection it looks
like we don't (and anyways, if we leaked as much as before, just without
the integer overflow, well, that's still an improvement).
2013-07-22 23:09:04 +00:00
|
|
|
strlen(getevent(selitems[i])) + sizeof(sel_nl);
|
2001-05-06 14:35:20 +00:00
|
|
|
|
2003-03-29 16:14:26 +00:00
|
|
|
clipdata = snewn(size, char);
|
2001-05-06 14:35:20 +00:00
|
|
|
if (clipdata) {
|
|
|
|
char *p = clipdata;
|
|
|
|
for (i = 0; i < count; i++) {
|
Don't grow logevent buf indefinitely
The PuTTY GUIs (Unix and Windows) maintain an in-memory event log
for display to users as they request. This uses ints for tracking
eventlog size, which is subject to memory exhaustion and (given
enough heap space) overflow attacks by servers (via, e.g., constant
rekeying).
Also a bounded log is more user-friendly. It is rare to want more
than the initial logging and the logging from a few recent rekey
events.
The Windows fix has been tested using Dr. Memory as a valgrind
substitute. No errors corresponding to the affected code showed up.
The Dr. Memory results.txt was split into a file per-error and then
grep Error $(grep -l windlg *)|cut -d: -f3-|sort |uniq -c
was used to compare. Differences arose from different usage of the GUI,
but no error could be traced to the code modified in this commit.
The Unix fix has been tested using valgrind. We don't destroy the
eventlog_stuff eventlog arrays, so we can't be entirely sure that we
don't leak more than we did before, but from code inspection it looks
like we don't (and anyways, if we leaked as much as before, just without
the integer overflow, well, that's still an improvement).
2013-07-22 23:09:04 +00:00
|
|
|
char *q = getevent(selitems[i]);
|
2001-05-06 14:35:20 +00:00
|
|
|
int qlen = strlen(q);
|
|
|
|
memcpy(p, q, qlen);
|
|
|
|
p += qlen;
|
|
|
|
memcpy(p, sel_nl, sizeof(sel_nl));
|
|
|
|
p += sizeof(sel_nl);
|
|
|
|
}
|
2017-12-09 12:00:13 +00:00
|
|
|
write_aclip(NULL, CLIP_SYSTEM, clipdata, size, TRUE);
|
2001-05-06 14:35:20 +00:00
|
|
|
sfree(clipdata);
|
|
|
|
}
|
|
|
|
sfree(selitems);
|
|
|
|
|
Don't grow logevent buf indefinitely
The PuTTY GUIs (Unix and Windows) maintain an in-memory event log
for display to users as they request. This uses ints for tracking
eventlog size, which is subject to memory exhaustion and (given
enough heap space) overflow attacks by servers (via, e.g., constant
rekeying).
Also a bounded log is more user-friendly. It is rare to want more
than the initial logging and the logging from a few recent rekey
events.
The Windows fix has been tested using Dr. Memory as a valgrind
substitute. No errors corresponding to the affected code showed up.
The Dr. Memory results.txt was split into a file per-error and then
grep Error $(grep -l windlg *)|cut -d: -f3-|sort |uniq -c
was used to compare. Differences arose from different usage of the GUI,
but no error could be traced to the code modified in this commit.
The Unix fix has been tested using valgrind. We don't destroy the
eventlog_stuff eventlog arrays, so we can't be entirely sure that we
don't leak more than we did before, but from code inspection it looks
like we don't (and anyways, if we leaked as much as before, just without
the integer overflow, well, that's still an improvement).
2013-07-22 23:09:04 +00:00
|
|
|
for (i = 0; i < (ninitial + ncircular); i++)
|
2001-05-06 14:35:20 +00:00
|
|
|
SendDlgItemMessage(hwnd, IDN_LIST, LB_SETSEL,
|
|
|
|
FALSE, i);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return 0;
|
1999-01-08 13:02:13 +00:00
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
case WM_CLOSE:
|
|
|
|
logbox = NULL;
|
2001-05-06 14:35:20 +00:00
|
|
|
SetActiveWindow(GetParent(hwnd));
|
|
|
|
DestroyWindow(hwnd);
|
1999-01-08 13:02:13 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2016-04-02 13:10:27 +00:00
|
|
|
static INT_PTR CALLBACK LicenceProc(HWND hwnd, UINT msg,
|
|
|
|
WPARAM wParam, LPARAM lParam)
|
2001-05-06 14:35:20 +00:00
|
|
|
{
|
1999-02-20 18:12:47 +00:00
|
|
|
switch (msg) {
|
|
|
|
case WM_INITDIALOG:
|
2003-04-06 14:11:33 +00:00
|
|
|
{
|
|
|
|
char *str = dupprintf("%s Licence", appname);
|
|
|
|
SetWindowText(hwnd, str);
|
|
|
|
sfree(str);
|
2015-12-22 12:43:31 +00:00
|
|
|
SetDlgItemText(hwnd, IDA_TEXT, LICENCE_TEXT("\r\n\r\n"));
|
2003-04-06 14:11:33 +00:00
|
|
|
}
|
1999-02-20 18:12:47 +00:00
|
|
|
return 1;
|
|
|
|
case WM_COMMAND:
|
|
|
|
switch (LOWORD(wParam)) {
|
|
|
|
case IDOK:
|
2004-10-27 15:50:52 +00:00
|
|
|
case IDCANCEL:
|
2000-09-29 08:42:55 +00:00
|
|
|
EndDialog(hwnd, 1);
|
1999-02-20 18:12:47 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
case WM_CLOSE:
|
2000-09-29 08:42:55 +00:00
|
|
|
EndDialog(hwnd, 1);
|
1999-02-20 18:12:47 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2016-04-02 13:10:27 +00:00
|
|
|
static INT_PTR CALLBACK AboutProc(HWND hwnd, UINT msg,
|
|
|
|
WPARAM wParam, LPARAM lParam)
|
2001-05-06 14:35:20 +00:00
|
|
|
{
|
2003-04-06 14:11:33 +00:00
|
|
|
char *str;
|
|
|
|
|
1999-01-08 13:02:13 +00:00
|
|
|
switch (msg) {
|
|
|
|
case WM_INITDIALOG:
|
2003-04-06 14:11:33 +00:00
|
|
|
str = dupprintf("About %s", appname);
|
|
|
|
SetWindowText(hwnd, str);
|
|
|
|
sfree(str);
|
2015-12-22 10:18:48 +00:00
|
|
|
{
|
2017-01-21 14:55:53 +00:00
|
|
|
char *buildinfo_text = buildinfo("\r\n");
|
2015-12-22 10:18:48 +00:00
|
|
|
char *text = dupprintf
|
2017-01-21 14:55:53 +00:00
|
|
|
("%s\r\n\r\n%s\r\n\r\n%s\r\n\r\n%s",
|
|
|
|
appname, ver, buildinfo_text,
|
2015-12-22 12:43:31 +00:00
|
|
|
"\251 " SHORT_COPYRIGHT_DETAILS ". All rights reserved.");
|
2017-01-21 14:55:53 +00:00
|
|
|
sfree(buildinfo_text);
|
2015-12-22 10:18:48 +00:00
|
|
|
SetDlgItemText(hwnd, IDA_TEXT, text);
|
|
|
|
sfree(text);
|
|
|
|
}
|
1999-01-08 13:02:13 +00:00
|
|
|
return 1;
|
|
|
|
case WM_COMMAND:
|
|
|
|
switch (LOWORD(wParam)) {
|
|
|
|
case IDOK:
|
2001-05-06 14:35:20 +00:00
|
|
|
case IDCANCEL:
|
|
|
|
EndDialog(hwnd, TRUE);
|
1999-01-08 13:02:13 +00:00
|
|
|
return 0;
|
|
|
|
case IDA_LICENCE:
|
|
|
|
EnableWindow(hwnd, 0);
|
2001-05-06 14:35:20 +00:00
|
|
|
DialogBox(hinst, MAKEINTRESOURCE(IDD_LICENCEBOX),
|
2004-10-27 15:50:52 +00:00
|
|
|
hwnd, LicenceProc);
|
1999-01-08 13:02:13 +00:00
|
|
|
EnableWindow(hwnd, 1);
|
2001-05-06 14:35:20 +00:00
|
|
|
SetActiveWindow(hwnd);
|
1999-01-08 13:02:13 +00:00
|
|
|
return 0;
|
2001-04-09 12:23:45 +00:00
|
|
|
|
2001-05-06 14:35:20 +00:00
|
|
|
case IDA_WEB:
|
|
|
|
/* Load web browser */
|
|
|
|
ShellExecute(hwnd, "open",
|
2017-05-07 15:29:01 +00:00
|
|
|
"https://www.chiark.greenend.org.uk/~sgtatham/putty/",
|
2001-05-06 14:35:20 +00:00
|
|
|
0, 0, SW_SHOWDEFAULT);
|
|
|
|
return 0;
|
1999-01-08 13:02:13 +00:00
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
case WM_CLOSE:
|
2001-05-06 14:35:20 +00:00
|
|
|
EndDialog(hwnd, TRUE);
|
1999-01-08 13:02:13 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2005-02-27 23:57:17 +00:00
|
|
|
static int SaneDialogBox(HINSTANCE hinst,
|
|
|
|
LPCTSTR tmpl,
|
|
|
|
HWND hwndparent,
|
|
|
|
DLGPROC lpDialogFunc)
|
|
|
|
{
|
|
|
|
WNDCLASS wc;
|
|
|
|
HWND hwnd;
|
|
|
|
MSG msg;
|
|
|
|
int flags;
|
|
|
|
int ret;
|
|
|
|
int gm;
|
|
|
|
|
|
|
|
wc.style = CS_DBLCLKS | CS_SAVEBITS | CS_BYTEALIGNWINDOW;
|
|
|
|
wc.lpfnWndProc = DefDlgProc;
|
|
|
|
wc.cbClsExtra = 0;
|
2005-05-21 14:16:43 +00:00
|
|
|
wc.cbWndExtra = DLGWINDOWEXTRA + 2*sizeof(LONG_PTR);
|
2005-02-27 23:57:17 +00:00
|
|
|
wc.hInstance = hinst;
|
|
|
|
wc.hIcon = NULL;
|
|
|
|
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
|
|
|
|
wc.hbrBackground = (HBRUSH) (COLOR_BACKGROUND +1);
|
|
|
|
wc.lpszMenuName = NULL;
|
|
|
|
wc.lpszClassName = "PuTTYConfigBox";
|
|
|
|
RegisterClass(&wc);
|
|
|
|
|
|
|
|
hwnd = CreateDialog(hinst, tmpl, hwndparent, lpDialogFunc);
|
|
|
|
|
2005-05-21 14:16:43 +00:00
|
|
|
SetWindowLongPtr(hwnd, BOXFLAGS, 0); /* flags */
|
|
|
|
SetWindowLongPtr(hwnd, BOXRESULT, 0); /* result from SaneEndDialog */
|
2005-02-27 23:57:17 +00:00
|
|
|
|
|
|
|
while ((gm=GetMessage(&msg, NULL, 0, 0)) > 0) {
|
2005-05-21 14:16:43 +00:00
|
|
|
flags=GetWindowLongPtr(hwnd, BOXFLAGS);
|
2005-02-27 23:57:17 +00:00
|
|
|
if (!(flags & DF_END) && !IsDialogMessage(hwnd, &msg))
|
|
|
|
DispatchMessage(&msg);
|
|
|
|
if (flags & DF_END)
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (gm == 0)
|
|
|
|
PostQuitMessage(msg.wParam); /* We got a WM_QUIT, pass it on */
|
|
|
|
|
2005-05-21 14:16:43 +00:00
|
|
|
ret=GetWindowLongPtr(hwnd, BOXRESULT);
|
2005-02-27 23:57:17 +00:00
|
|
|
DestroyWindow(hwnd);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void SaneEndDialog(HWND hwnd, int ret)
|
|
|
|
{
|
2005-05-21 14:16:43 +00:00
|
|
|
SetWindowLongPtr(hwnd, BOXRESULT, ret);
|
|
|
|
SetWindowLongPtr(hwnd, BOXFLAGS, DF_END);
|
2005-02-27 23:57:17 +00:00
|
|
|
}
|
|
|
|
|
2000-10-12 12:56:33 +00:00
|
|
|
/*
|
|
|
|
* Null dialog procedure.
|
|
|
|
*/
|
2016-04-02 13:10:27 +00:00
|
|
|
static INT_PTR CALLBACK NullDlgProc(HWND hwnd, UINT msg,
|
|
|
|
WPARAM wParam, LPARAM lParam)
|
2001-05-06 14:35:20 +00:00
|
|
|
{
|
2000-10-12 12:56:33 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2003-03-05 22:07:40 +00:00
|
|
|
enum {
|
|
|
|
IDCX_ABOUT = IDC_ABOUT,
|
|
|
|
IDCX_TVSTATIC,
|
|
|
|
IDCX_TREEVIEW,
|
|
|
|
IDCX_STDBASE,
|
|
|
|
IDCX_PANELBASE = IDCX_STDBASE + 32
|
2000-10-09 12:16:27 +00:00
|
|
|
};
|
|
|
|
|
2000-10-09 15:51:14 +00:00
|
|
|
struct treeview_faff {
|
|
|
|
HWND treeview;
|
|
|
|
HTREEITEM lastat[4];
|
|
|
|
};
|
|
|
|
|
|
|
|
static HTREEITEM treeview_insert(struct treeview_faff *faff,
|
2003-03-05 22:07:40 +00:00
|
|
|
int level, char *text, char *path)
|
2001-05-06 14:35:20 +00:00
|
|
|
{
|
2000-10-09 15:51:14 +00:00
|
|
|
TVINSERTSTRUCT ins;
|
|
|
|
int i;
|
|
|
|
HTREEITEM newitem;
|
2001-05-06 14:35:20 +00:00
|
|
|
ins.hParent = (level > 0 ? faff->lastat[level - 1] : TVI_ROOT);
|
2000-10-09 15:51:14 +00:00
|
|
|
ins.hInsertAfter = faff->lastat[level];
|
2000-10-09 16:12:51 +00:00
|
|
|
#if _WIN32_IE >= 0x0400 && defined NONAMELESSUNION
|
|
|
|
#define INSITEM DUMMYUNIONNAME.item
|
|
|
|
#else
|
|
|
|
#define INSITEM item
|
|
|
|
#endif
|
2003-03-05 22:07:40 +00:00
|
|
|
ins.INSITEM.mask = TVIF_TEXT | TVIF_PARAM;
|
2000-10-09 16:12:51 +00:00
|
|
|
ins.INSITEM.pszText = text;
|
2003-03-05 22:07:40 +00:00
|
|
|
ins.INSITEM.cchTextMax = strlen(text)+1;
|
|
|
|
ins.INSITEM.lParam = (LPARAM)path;
|
2000-10-09 15:51:14 +00:00
|
|
|
newitem = TreeView_InsertItem(faff->treeview, &ins);
|
|
|
|
if (level > 0)
|
2001-05-06 14:35:20 +00:00
|
|
|
TreeView_Expand(faff->treeview, faff->lastat[level - 1],
|
2007-01-16 18:48:47 +00:00
|
|
|
(level > 1 ? TVE_COLLAPSE : TVE_EXPAND));
|
2000-10-09 15:51:14 +00:00
|
|
|
faff->lastat[level] = newitem;
|
2001-05-06 14:35:20 +00:00
|
|
|
for (i = level + 1; i < 4; i++)
|
|
|
|
faff->lastat[i] = NULL;
|
2000-10-09 15:51:14 +00:00
|
|
|
return newitem;
|
|
|
|
}
|
|
|
|
|
2000-10-09 12:16:27 +00:00
|
|
|
/*
|
2001-01-22 17:17:26 +00:00
|
|
|
* Create the panelfuls of controls in the configuration box.
|
|
|
|
*/
|
2003-03-05 22:07:40 +00:00
|
|
|
static void create_controls(HWND hwnd, char *path)
|
2001-05-06 14:35:20 +00:00
|
|
|
{
|
2003-03-05 22:07:40 +00:00
|
|
|
struct ctlpos cp;
|
|
|
|
int index;
|
|
|
|
int base_id;
|
|
|
|
struct winctrls *wc;
|
2001-01-22 17:17:26 +00:00
|
|
|
|
2003-03-05 22:07:40 +00:00
|
|
|
if (!path[0]) {
|
|
|
|
/*
|
|
|
|
* Here we must create the basic standard controls.
|
|
|
|
*/
|
|
|
|
ctlposinit(&cp, hwnd, 3, 3, 235);
|
|
|
|
wc = &ctrls_base;
|
|
|
|
base_id = IDCX_STDBASE;
|
|
|
|
} else {
|
|
|
|
/*
|
|
|
|
* Otherwise, we're creating the controls for a particular
|
|
|
|
* panel.
|
|
|
|
*/
|
2004-12-30 16:45:11 +00:00
|
|
|
ctlposinit(&cp, hwnd, 100, 3, 13);
|
2003-03-05 22:07:40 +00:00
|
|
|
wc = &ctrls_panel;
|
|
|
|
base_id = IDCX_PANELBASE;
|
2001-01-22 17:17:26 +00:00
|
|
|
}
|
|
|
|
|
2003-03-05 22:07:40 +00:00
|
|
|
for (index=-1; (index = ctrl_find_path(ctrlbox, path, index)) >= 0 ;) {
|
|
|
|
struct controlset *s = ctrlbox->ctrlsets[index];
|
|
|
|
winctrl_layout(&dp, wc, &cp, s, &base_id);
|
2001-05-13 11:58:36 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2001-01-22 17:17:26 +00:00
|
|
|
/*
|
|
|
|
* This function is the configuration box.
|
2005-03-20 22:28:13 +00:00
|
|
|
* (Being a dialog procedure, in general it returns 0 if the default
|
|
|
|
* dialog processing should be performed, and 1 if it should not.)
|
2000-10-09 12:16:27 +00:00
|
|
|
*/
|
2016-04-02 13:10:27 +00:00
|
|
|
static INT_PTR CALLBACK GenericMainDlgProc(HWND hwnd, UINT msg,
|
|
|
|
WPARAM wParam, LPARAM lParam)
|
2001-05-06 14:35:20 +00:00
|
|
|
{
|
2000-10-09 15:51:14 +00:00
|
|
|
HWND hw, treeview;
|
|
|
|
struct treeview_faff tvfaff;
|
2003-03-05 22:07:40 +00:00
|
|
|
int ret;
|
1999-01-08 13:02:13 +00:00
|
|
|
|
|
|
|
switch (msg) {
|
|
|
|
case WM_INITDIALOG:
|
2003-03-05 22:07:40 +00:00
|
|
|
dp.hwnd = hwnd;
|
|
|
|
create_controls(hwnd, ""); /* Open and Cancel buttons etc */
|
2003-04-06 14:11:33 +00:00
|
|
|
SetWindowText(hwnd, dp.wintitle);
|
2005-05-21 14:16:43 +00:00
|
|
|
SetWindowLongPtr(hwnd, GWLP_USERDATA, 0);
|
2006-12-17 11:16:07 +00:00
|
|
|
if (has_help())
|
2005-05-21 14:16:43 +00:00
|
|
|
SetWindowLongPtr(hwnd, GWL_EXSTYLE,
|
|
|
|
GetWindowLongPtr(hwnd, GWL_EXSTYLE) |
|
|
|
|
WS_EX_CONTEXTHELP);
|
2001-12-06 13:28:02 +00:00
|
|
|
else {
|
|
|
|
HWND item = GetDlgItem(hwnd, IDC_HELPBTN);
|
|
|
|
if (item)
|
|
|
|
DestroyWindow(item);
|
|
|
|
}
|
2001-05-13 10:45:56 +00:00
|
|
|
SendMessage(hwnd, WM_SETICON, (WPARAM) ICON_BIG,
|
|
|
|
(LPARAM) LoadIcon(hinst, MAKEINTRESOURCE(IDI_CFGICON)));
|
2000-10-09 12:16:27 +00:00
|
|
|
/*
|
|
|
|
* Centre the window.
|
|
|
|
*/
|
|
|
|
{ /* centre the window */
|
|
|
|
RECT rs, rd;
|
|
|
|
|
|
|
|
hw = GetDesktopWindow();
|
2001-05-06 14:35:20 +00:00
|
|
|
if (GetWindowRect(hw, &rs) && GetWindowRect(hwnd, &rd))
|
|
|
|
MoveWindow(hwnd,
|
|
|
|
(rs.right + rs.left + rd.left - rd.right) / 2,
|
|
|
|
(rs.bottom + rs.top + rd.top - rd.bottom) / 2,
|
|
|
|
rd.right - rd.left, rd.bottom - rd.top, TRUE);
|
2000-10-09 12:16:27 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
2000-10-09 15:51:14 +00:00
|
|
|
* Create the tree view.
|
2000-10-09 12:16:27 +00:00
|
|
|
*/
|
2001-05-06 14:35:20 +00:00
|
|
|
{
|
|
|
|
RECT r;
|
2000-10-09 12:16:27 +00:00
|
|
|
WPARAM font;
|
2001-05-06 14:35:20 +00:00
|
|
|
HWND tvstatic;
|
|
|
|
|
|
|
|
r.left = 3;
|
2004-12-30 16:45:11 +00:00
|
|
|
r.right = r.left + 95;
|
2001-05-06 14:35:20 +00:00
|
|
|
r.top = 3;
|
|
|
|
r.bottom = r.top + 10;
|
|
|
|
MapDialogRect(hwnd, &r);
|
|
|
|
tvstatic = CreateWindowEx(0, "STATIC", "Cate&gory:",
|
|
|
|
WS_CHILD | WS_VISIBLE,
|
|
|
|
r.left, r.top,
|
|
|
|
r.right - r.left, r.bottom - r.top,
|
|
|
|
hwnd, (HMENU) IDCX_TVSTATIC, hinst,
|
|
|
|
NULL);
|
2000-10-09 12:16:27 +00:00
|
|
|
font = SendMessage(hwnd, WM_GETFONT, 0, 0);
|
2000-10-09 15:51:14 +00:00
|
|
|
SendMessage(tvstatic, WM_SETFONT, font, MAKELPARAM(TRUE, 0));
|
|
|
|
|
2001-05-06 14:35:20 +00:00
|
|
|
r.left = 3;
|
2004-12-30 16:45:11 +00:00
|
|
|
r.right = r.left + 95;
|
2001-05-06 14:35:20 +00:00
|
|
|
r.top = 13;
|
2001-10-17 21:21:03 +00:00
|
|
|
r.bottom = r.top + 219;
|
2001-05-06 14:35:20 +00:00
|
|
|
MapDialogRect(hwnd, &r);
|
|
|
|
treeview = CreateWindowEx(WS_EX_CLIENTEDGE, WC_TREEVIEW, "",
|
|
|
|
WS_CHILD | WS_VISIBLE |
|
|
|
|
WS_TABSTOP | TVS_HASLINES |
|
|
|
|
TVS_DISABLEDRAGDROP | TVS_HASBUTTONS
|
|
|
|
| TVS_LINESATROOT |
|
|
|
|
TVS_SHOWSELALWAYS, r.left, r.top,
|
|
|
|
r.right - r.left, r.bottom - r.top,
|
|
|
|
hwnd, (HMENU) IDCX_TREEVIEW, hinst,
|
|
|
|
NULL);
|
2000-10-09 15:51:14 +00:00
|
|
|
font = SendMessage(hwnd, WM_GETFONT, 0, 0);
|
|
|
|
SendMessage(treeview, WM_SETFONT, font, MAKELPARAM(TRUE, 0));
|
2001-05-06 14:35:20 +00:00
|
|
|
tvfaff.treeview = treeview;
|
|
|
|
memset(tvfaff.lastat, 0, sizeof(tvfaff.lastat));
|
|
|
|
}
|
2000-10-09 12:16:27 +00:00
|
|
|
|
|
|
|
/*
|
2001-01-22 17:17:26 +00:00
|
|
|
* Set up the tree view contents.
|
2000-10-09 12:16:27 +00:00
|
|
|
*/
|
2003-03-05 22:07:40 +00:00
|
|
|
{
|
|
|
|
HTREEITEM hfirst = NULL;
|
|
|
|
int i;
|
|
|
|
char *path = NULL;
|
Fix accidental dependence on Windows API quirk in config box.
Our config boxes are constructed using the CreateDialog() API
function, rather than the modal DialogBox(). CreateDialog() is not
that different from CreateWindow(), so windows created with it don't
appear on the screen automatically; MSDN says that they must be shown
via ShowWindow(), just like non-dialog windows have to be. But we
weren't doing that at any point!
So how was our config box ever getting displayed at all? Apparently by
sheer chance, it turns out. The handler for a selection change in the
tree view, which has to delete a whole panel of controls and creates a
different set, surrounds that procedure with some WM_SETREDRAW calls
and an InvalidateRect(), to prevent flicker while lots of changes were
being made. And the creation of the _first_ panelful of controls, at
dialog box setup, was done by simply selecting an item in the treeview
and expecting that handler to be recursively called. And it appears
that calling WM_SETREDRAW(TRUE) and then InvalidateRect was
undocumentedly having an effect equivalent to the ShowWindow() we
should have called, so that we never noticed the latter was missing.
But a recent Vista update (all reports implicate KB3057839) has caused
that not to work any more: on an updated Vista machine, in some
desktop configurations, it seems that any attempt to fiddle with
WM_SETREDRAW during dialog setup can leave the dialog box in a really
unhelpful invisible state - the window is _physically there_ (you can
see its taskbar entry, and the mouse pointer changes as you move over
where its edit boxes are), but 100% transparent.
So now we're doing something a bit more sensible. The first panelful
of controls is created directly by the WM_INITDIALOG handler, rather
than recursing into code that wasn't really designed to run at setup
time. To be on the safe side, that handler for treeview selection
change is also disabled until the WM_INITDIALOG handler has finished
(like we already did with the WM_COMMAND handler), so that we can be
sure of not accidentally messing about with WM_SETREDRAW at all during
setup. And at the end of setup, we show the window in the sensible
way, by a docs-approved call to ShowWindow().
This appears (on the one machine I've so far tested it on) to fix the
Vista invisible-window issue, and also it should be more API-compliant
and hence safer in future.
2015-06-18 06:05:19 +00:00
|
|
|
char *firstpath = NULL;
|
2003-03-05 22:07:40 +00:00
|
|
|
|
|
|
|
for (i = 0; i < ctrlbox->nctrlsets; i++) {
|
|
|
|
struct controlset *s = ctrlbox->ctrlsets[i];
|
|
|
|
HTREEITEM item;
|
|
|
|
int j;
|
|
|
|
char *c;
|
|
|
|
|
|
|
|
if (!s->pathname[0])
|
|
|
|
continue;
|
|
|
|
j = path ? ctrl_path_compare(s->pathname, path) : 0;
|
|
|
|
if (j == INT_MAX)
|
|
|
|
continue; /* same path, nothing to add to tree */
|
|
|
|
|
|
|
|
/*
|
|
|
|
* We expect never to find an implicit path
|
|
|
|
* component. For example, we expect never to see
|
|
|
|
* A/B/C followed by A/D/E, because that would
|
|
|
|
* _implicitly_ create A/D. All our path prefixes
|
|
|
|
* are expected to contain actual controls and be
|
|
|
|
* selectable in the treeview; so we would expect
|
|
|
|
* to see A/D _explicitly_ before encountering
|
|
|
|
* A/D/E.
|
|
|
|
*/
|
|
|
|
assert(j == ctrl_path_elements(s->pathname) - 1);
|
|
|
|
|
|
|
|
c = strrchr(s->pathname, '/');
|
|
|
|
if (!c)
|
|
|
|
c = s->pathname;
|
|
|
|
else
|
|
|
|
c++;
|
|
|
|
|
|
|
|
item = treeview_insert(&tvfaff, j, c, s->pathname);
|
Fix accidental dependence on Windows API quirk in config box.
Our config boxes are constructed using the CreateDialog() API
function, rather than the modal DialogBox(). CreateDialog() is not
that different from CreateWindow(), so windows created with it don't
appear on the screen automatically; MSDN says that they must be shown
via ShowWindow(), just like non-dialog windows have to be. But we
weren't doing that at any point!
So how was our config box ever getting displayed at all? Apparently by
sheer chance, it turns out. The handler for a selection change in the
tree view, which has to delete a whole panel of controls and creates a
different set, surrounds that procedure with some WM_SETREDRAW calls
and an InvalidateRect(), to prevent flicker while lots of changes were
being made. And the creation of the _first_ panelful of controls, at
dialog box setup, was done by simply selecting an item in the treeview
and expecting that handler to be recursively called. And it appears
that calling WM_SETREDRAW(TRUE) and then InvalidateRect was
undocumentedly having an effect equivalent to the ShowWindow() we
should have called, so that we never noticed the latter was missing.
But a recent Vista update (all reports implicate KB3057839) has caused
that not to work any more: on an updated Vista machine, in some
desktop configurations, it seems that any attempt to fiddle with
WM_SETREDRAW during dialog setup can leave the dialog box in a really
unhelpful invisible state - the window is _physically there_ (you can
see its taskbar entry, and the mouse pointer changes as you move over
where its edit boxes are), but 100% transparent.
So now we're doing something a bit more sensible. The first panelful
of controls is created directly by the WM_INITDIALOG handler, rather
than recursing into code that wasn't really designed to run at setup
time. To be on the safe side, that handler for treeview selection
change is also disabled until the WM_INITDIALOG handler has finished
(like we already did with the WM_COMMAND handler), so that we can be
sure of not accidentally messing about with WM_SETREDRAW at all during
setup. And at the end of setup, we show the window in the sensible
way, by a docs-approved call to ShowWindow().
This appears (on the one machine I've so far tested it on) to fix the
Vista invisible-window issue, and also it should be more API-compliant
and hence safer in future.
2015-06-18 06:05:19 +00:00
|
|
|
if (!hfirst) {
|
2003-03-05 22:07:40 +00:00
|
|
|
hfirst = item;
|
Fix accidental dependence on Windows API quirk in config box.
Our config boxes are constructed using the CreateDialog() API
function, rather than the modal DialogBox(). CreateDialog() is not
that different from CreateWindow(), so windows created with it don't
appear on the screen automatically; MSDN says that they must be shown
via ShowWindow(), just like non-dialog windows have to be. But we
weren't doing that at any point!
So how was our config box ever getting displayed at all? Apparently by
sheer chance, it turns out. The handler for a selection change in the
tree view, which has to delete a whole panel of controls and creates a
different set, surrounds that procedure with some WM_SETREDRAW calls
and an InvalidateRect(), to prevent flicker while lots of changes were
being made. And the creation of the _first_ panelful of controls, at
dialog box setup, was done by simply selecting an item in the treeview
and expecting that handler to be recursively called. And it appears
that calling WM_SETREDRAW(TRUE) and then InvalidateRect was
undocumentedly having an effect equivalent to the ShowWindow() we
should have called, so that we never noticed the latter was missing.
But a recent Vista update (all reports implicate KB3057839) has caused
that not to work any more: on an updated Vista machine, in some
desktop configurations, it seems that any attempt to fiddle with
WM_SETREDRAW during dialog setup can leave the dialog box in a really
unhelpful invisible state - the window is _physically there_ (you can
see its taskbar entry, and the mouse pointer changes as you move over
where its edit boxes are), but 100% transparent.
So now we're doing something a bit more sensible. The first panelful
of controls is created directly by the WM_INITDIALOG handler, rather
than recursing into code that wasn't really designed to run at setup
time. To be on the safe side, that handler for treeview selection
change is also disabled until the WM_INITDIALOG handler has finished
(like we already did with the WM_COMMAND handler), so that we can be
sure of not accidentally messing about with WM_SETREDRAW at all during
setup. And at the end of setup, we show the window in the sensible
way, by a docs-approved call to ShowWindow().
This appears (on the one machine I've so far tested it on) to fix the
Vista invisible-window issue, and also it should be more API-compliant
and hence safer in future.
2015-06-18 06:05:19 +00:00
|
|
|
firstpath = s->pathname;
|
|
|
|
}
|
2003-03-05 22:07:40 +00:00
|
|
|
|
|
|
|
path = s->pathname;
|
2001-05-06 14:35:20 +00:00
|
|
|
}
|
|
|
|
|
2003-03-05 22:07:40 +00:00
|
|
|
/*
|
Fix accidental dependence on Windows API quirk in config box.
Our config boxes are constructed using the CreateDialog() API
function, rather than the modal DialogBox(). CreateDialog() is not
that different from CreateWindow(), so windows created with it don't
appear on the screen automatically; MSDN says that they must be shown
via ShowWindow(), just like non-dialog windows have to be. But we
weren't doing that at any point!
So how was our config box ever getting displayed at all? Apparently by
sheer chance, it turns out. The handler for a selection change in the
tree view, which has to delete a whole panel of controls and creates a
different set, surrounds that procedure with some WM_SETREDRAW calls
and an InvalidateRect(), to prevent flicker while lots of changes were
being made. And the creation of the _first_ panelful of controls, at
dialog box setup, was done by simply selecting an item in the treeview
and expecting that handler to be recursively called. And it appears
that calling WM_SETREDRAW(TRUE) and then InvalidateRect was
undocumentedly having an effect equivalent to the ShowWindow() we
should have called, so that we never noticed the latter was missing.
But a recent Vista update (all reports implicate KB3057839) has caused
that not to work any more: on an updated Vista machine, in some
desktop configurations, it seems that any attempt to fiddle with
WM_SETREDRAW during dialog setup can leave the dialog box in a really
unhelpful invisible state - the window is _physically there_ (you can
see its taskbar entry, and the mouse pointer changes as you move over
where its edit boxes are), but 100% transparent.
So now we're doing something a bit more sensible. The first panelful
of controls is created directly by the WM_INITDIALOG handler, rather
than recursing into code that wasn't really designed to run at setup
time. To be on the safe side, that handler for treeview selection
change is also disabled until the WM_INITDIALOG handler has finished
(like we already did with the WM_COMMAND handler), so that we can be
sure of not accidentally messing about with WM_SETREDRAW at all during
setup. And at the end of setup, we show the window in the sensible
way, by a docs-approved call to ShowWindow().
This appears (on the one machine I've so far tested it on) to fix the
Vista invisible-window issue, and also it should be more API-compliant
and hence safer in future.
2015-06-18 06:05:19 +00:00
|
|
|
* Put the treeview selection on to the first panel in the
|
|
|
|
* ctrlbox.
|
2003-03-05 22:07:40 +00:00
|
|
|
*/
|
|
|
|
TreeView_SelectItem(treeview, hfirst);
|
Fix accidental dependence on Windows API quirk in config box.
Our config boxes are constructed using the CreateDialog() API
function, rather than the modal DialogBox(). CreateDialog() is not
that different from CreateWindow(), so windows created with it don't
appear on the screen automatically; MSDN says that they must be shown
via ShowWindow(), just like non-dialog windows have to be. But we
weren't doing that at any point!
So how was our config box ever getting displayed at all? Apparently by
sheer chance, it turns out. The handler for a selection change in the
tree view, which has to delete a whole panel of controls and creates a
different set, surrounds that procedure with some WM_SETREDRAW calls
and an InvalidateRect(), to prevent flicker while lots of changes were
being made. And the creation of the _first_ panelful of controls, at
dialog box setup, was done by simply selecting an item in the treeview
and expecting that handler to be recursively called. And it appears
that calling WM_SETREDRAW(TRUE) and then InvalidateRect was
undocumentedly having an effect equivalent to the ShowWindow() we
should have called, so that we never noticed the latter was missing.
But a recent Vista update (all reports implicate KB3057839) has caused
that not to work any more: on an updated Vista machine, in some
desktop configurations, it seems that any attempt to fiddle with
WM_SETREDRAW during dialog setup can leave the dialog box in a really
unhelpful invisible state - the window is _physically there_ (you can
see its taskbar entry, and the mouse pointer changes as you move over
where its edit boxes are), but 100% transparent.
So now we're doing something a bit more sensible. The first panelful
of controls is created directly by the WM_INITDIALOG handler, rather
than recursing into code that wasn't really designed to run at setup
time. To be on the safe side, that handler for treeview selection
change is also disabled until the WM_INITDIALOG handler has finished
(like we already did with the WM_COMMAND handler), so that we can be
sure of not accidentally messing about with WM_SETREDRAW at all during
setup. And at the end of setup, we show the window in the sensible
way, by a docs-approved call to ShowWindow().
This appears (on the one machine I've so far tested it on) to fix the
Vista invisible-window issue, and also it should be more API-compliant
and hence safer in future.
2015-06-18 06:05:19 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* And create the actual control set for that panel, to
|
|
|
|
* match the initial treeview selection.
|
|
|
|
*/
|
2015-07-25 10:07:38 +00:00
|
|
|
assert(firstpath); /* config.c must have given us _something_ */
|
Fix accidental dependence on Windows API quirk in config box.
Our config boxes are constructed using the CreateDialog() API
function, rather than the modal DialogBox(). CreateDialog() is not
that different from CreateWindow(), so windows created with it don't
appear on the screen automatically; MSDN says that they must be shown
via ShowWindow(), just like non-dialog windows have to be. But we
weren't doing that at any point!
So how was our config box ever getting displayed at all? Apparently by
sheer chance, it turns out. The handler for a selection change in the
tree view, which has to delete a whole panel of controls and creates a
different set, surrounds that procedure with some WM_SETREDRAW calls
and an InvalidateRect(), to prevent flicker while lots of changes were
being made. And the creation of the _first_ panelful of controls, at
dialog box setup, was done by simply selecting an item in the treeview
and expecting that handler to be recursively called. And it appears
that calling WM_SETREDRAW(TRUE) and then InvalidateRect was
undocumentedly having an effect equivalent to the ShowWindow() we
should have called, so that we never noticed the latter was missing.
But a recent Vista update (all reports implicate KB3057839) has caused
that not to work any more: on an updated Vista machine, in some
desktop configurations, it seems that any attempt to fiddle with
WM_SETREDRAW during dialog setup can leave the dialog box in a really
unhelpful invisible state - the window is _physically there_ (you can
see its taskbar entry, and the mouse pointer changes as you move over
where its edit boxes are), but 100% transparent.
So now we're doing something a bit more sensible. The first panelful
of controls is created directly by the WM_INITDIALOG handler, rather
than recursing into code that wasn't really designed to run at setup
time. To be on the safe side, that handler for treeview selection
change is also disabled until the WM_INITDIALOG handler has finished
(like we already did with the WM_COMMAND handler), so that we can be
sure of not accidentally messing about with WM_SETREDRAW at all during
setup. And at the end of setup, we show the window in the sensible
way, by a docs-approved call to ShowWindow().
This appears (on the one machine I've so far tested it on) to fix the
Vista invisible-window issue, and also it should be more API-compliant
and hence safer in future.
2015-06-18 06:05:19 +00:00
|
|
|
create_controls(hwnd, firstpath);
|
|
|
|
dlg_refresh(NULL, &dp); /* and set up control values */
|
2003-03-05 22:07:40 +00:00
|
|
|
}
|
2001-05-06 14:35:20 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Set focus into the first available control.
|
|
|
|
*/
|
|
|
|
{
|
2003-03-05 22:07:40 +00:00
|
|
|
int i;
|
|
|
|
struct winctrl *c;
|
|
|
|
|
|
|
|
for (i = 0; (c = winctrl_findbyindex(&ctrls_panel, i)) != NULL;
|
|
|
|
i++) {
|
|
|
|
if (c->ctrl) {
|
|
|
|
dlg_set_focus(c->ctrl, &dp);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2001-05-06 14:35:20 +00:00
|
|
|
}
|
2000-10-09 12:16:27 +00:00
|
|
|
|
Fix accidental dependence on Windows API quirk in config box.
Our config boxes are constructed using the CreateDialog() API
function, rather than the modal DialogBox(). CreateDialog() is not
that different from CreateWindow(), so windows created with it don't
appear on the screen automatically; MSDN says that they must be shown
via ShowWindow(), just like non-dialog windows have to be. But we
weren't doing that at any point!
So how was our config box ever getting displayed at all? Apparently by
sheer chance, it turns out. The handler for a selection change in the
tree view, which has to delete a whole panel of controls and creates a
different set, surrounds that procedure with some WM_SETREDRAW calls
and an InvalidateRect(), to prevent flicker while lots of changes were
being made. And the creation of the _first_ panelful of controls, at
dialog box setup, was done by simply selecting an item in the treeview
and expecting that handler to be recursively called. And it appears
that calling WM_SETREDRAW(TRUE) and then InvalidateRect was
undocumentedly having an effect equivalent to the ShowWindow() we
should have called, so that we never noticed the latter was missing.
But a recent Vista update (all reports implicate KB3057839) has caused
that not to work any more: on an updated Vista machine, in some
desktop configurations, it seems that any attempt to fiddle with
WM_SETREDRAW during dialog setup can leave the dialog box in a really
unhelpful invisible state - the window is _physically there_ (you can
see its taskbar entry, and the mouse pointer changes as you move over
where its edit boxes are), but 100% transparent.
So now we're doing something a bit more sensible. The first panelful
of controls is created directly by the WM_INITDIALOG handler, rather
than recursing into code that wasn't really designed to run at setup
time. To be on the safe side, that handler for treeview selection
change is also disabled until the WM_INITDIALOG handler has finished
(like we already did with the WM_COMMAND handler), so that we can be
sure of not accidentally messing about with WM_SETREDRAW at all during
setup. And at the end of setup, we show the window in the sensible
way, by a docs-approved call to ShowWindow().
This appears (on the one machine I've so far tested it on) to fix the
Vista invisible-window issue, and also it should be more API-compliant
and hence safer in future.
2015-06-18 06:05:19 +00:00
|
|
|
/*
|
|
|
|
* Now we've finished creating our initial set of controls,
|
|
|
|
* it's safe to actually show the window without risking setup
|
|
|
|
* flicker.
|
|
|
|
*/
|
|
|
|
ShowWindow(hwnd, SW_SHOWNORMAL);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Set the flag that activates a couple of the other message
|
|
|
|
* handlers below, which were disabled until now to avoid
|
|
|
|
* spurious firing during the above setup procedure.
|
|
|
|
*/
|
2005-05-21 14:16:43 +00:00
|
|
|
SetWindowLongPtr(hwnd, GWLP_USERDATA, 1);
|
2000-10-09 12:16:27 +00:00
|
|
|
return 0;
|
1999-02-18 10:39:23 +00:00
|
|
|
case WM_LBUTTONUP:
|
2001-05-06 14:35:20 +00:00
|
|
|
/*
|
|
|
|
* Button release should trigger WM_OK if there was a
|
|
|
|
* previous double click on the session list.
|
|
|
|
*/
|
|
|
|
ReleaseCapture();
|
2003-03-05 22:07:40 +00:00
|
|
|
if (dp.ended)
|
2003-06-16 23:55:26 +00:00
|
|
|
SaneEndDialog(hwnd, dp.endresult ? 1 : 0);
|
2001-05-06 14:35:20 +00:00
|
|
|
break;
|
2000-10-09 12:16:27 +00:00
|
|
|
case WM_NOTIFY:
|
2000-10-09 15:51:14 +00:00
|
|
|
if (LOWORD(wParam) == IDCX_TREEVIEW &&
|
2001-05-06 14:35:20 +00:00
|
|
|
((LPNMHDR) lParam)->code == TVN_SELCHANGED) {
|
Fix accidental dependence on Windows API quirk in config box.
Our config boxes are constructed using the CreateDialog() API
function, rather than the modal DialogBox(). CreateDialog() is not
that different from CreateWindow(), so windows created with it don't
appear on the screen automatically; MSDN says that they must be shown
via ShowWindow(), just like non-dialog windows have to be. But we
weren't doing that at any point!
So how was our config box ever getting displayed at all? Apparently by
sheer chance, it turns out. The handler for a selection change in the
tree view, which has to delete a whole panel of controls and creates a
different set, surrounds that procedure with some WM_SETREDRAW calls
and an InvalidateRect(), to prevent flicker while lots of changes were
being made. And the creation of the _first_ panelful of controls, at
dialog box setup, was done by simply selecting an item in the treeview
and expecting that handler to be recursively called. And it appears
that calling WM_SETREDRAW(TRUE) and then InvalidateRect was
undocumentedly having an effect equivalent to the ShowWindow() we
should have called, so that we never noticed the latter was missing.
But a recent Vista update (all reports implicate KB3057839) has caused
that not to work any more: on an updated Vista machine, in some
desktop configurations, it seems that any attempt to fiddle with
WM_SETREDRAW during dialog setup can leave the dialog box in a really
unhelpful invisible state - the window is _physically there_ (you can
see its taskbar entry, and the mouse pointer changes as you move over
where its edit boxes are), but 100% transparent.
So now we're doing something a bit more sensible. The first panelful
of controls is created directly by the WM_INITDIALOG handler, rather
than recursing into code that wasn't really designed to run at setup
time. To be on the safe side, that handler for treeview selection
change is also disabled until the WM_INITDIALOG handler has finished
(like we already did with the WM_COMMAND handler), so that we can be
sure of not accidentally messing about with WM_SETREDRAW at all during
setup. And at the end of setup, we show the window in the sensible
way, by a docs-approved call to ShowWindow().
This appears (on the one machine I've so far tested it on) to fix the
Vista invisible-window issue, and also it should be more API-compliant
and hence safer in future.
2015-06-18 06:05:19 +00:00
|
|
|
/*
|
|
|
|
* Selection-change events on the treeview cause us to do
|
|
|
|
* a flurry of control deletion and creation - but only
|
|
|
|
* after WM_INITDIALOG has finished. The initial
|
|
|
|
* selection-change event(s) during treeview setup are
|
|
|
|
* ignored.
|
|
|
|
*/
|
|
|
|
HTREEITEM i;
|
2000-10-09 15:51:14 +00:00
|
|
|
TVITEM item;
|
2000-10-09 12:16:27 +00:00
|
|
|
char buffer[64];
|
Fix accidental dependence on Windows API quirk in config box.
Our config boxes are constructed using the CreateDialog() API
function, rather than the modal DialogBox(). CreateDialog() is not
that different from CreateWindow(), so windows created with it don't
appear on the screen automatically; MSDN says that they must be shown
via ShowWindow(), just like non-dialog windows have to be. But we
weren't doing that at any point!
So how was our config box ever getting displayed at all? Apparently by
sheer chance, it turns out. The handler for a selection change in the
tree view, which has to delete a whole panel of controls and creates a
different set, surrounds that procedure with some WM_SETREDRAW calls
and an InvalidateRect(), to prevent flicker while lots of changes were
being made. And the creation of the _first_ panelful of controls, at
dialog box setup, was done by simply selecting an item in the treeview
and expecting that handler to be recursively called. And it appears
that calling WM_SETREDRAW(TRUE) and then InvalidateRect was
undocumentedly having an effect equivalent to the ShowWindow() we
should have called, so that we never noticed the latter was missing.
But a recent Vista update (all reports implicate KB3057839) has caused
that not to work any more: on an updated Vista machine, in some
desktop configurations, it seems that any attempt to fiddle with
WM_SETREDRAW during dialog setup can leave the dialog box in a really
unhelpful invisible state - the window is _physically there_ (you can
see its taskbar entry, and the mouse pointer changes as you move over
where its edit boxes are), but 100% transparent.
So now we're doing something a bit more sensible. The first panelful
of controls is created directly by the WM_INITDIALOG handler, rather
than recursing into code that wasn't really designed to run at setup
time. To be on the safe side, that handler for treeview selection
change is also disabled until the WM_INITDIALOG handler has finished
(like we already did with the WM_COMMAND handler), so that we can be
sure of not accidentally messing about with WM_SETREDRAW at all during
setup. And at the end of setup, we show the window in the sensible
way, by a docs-approved call to ShowWindow().
This appears (on the one machine I've so far tested it on) to fix the
Vista invisible-window issue, and also it should be more API-compliant
and hence safer in future.
2015-06-18 06:05:19 +00:00
|
|
|
|
|
|
|
if (GetWindowLongPtr(hwnd, GWLP_USERDATA) != 1)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
i = TreeView_GetSelection(((LPNMHDR) lParam)->hwndFrom);
|
2001-09-07 21:07:15 +00:00
|
|
|
|
|
|
|
SendMessage (hwnd, WM_SETREDRAW, FALSE, 0);
|
|
|
|
|
2001-05-06 14:35:20 +00:00
|
|
|
item.hItem = i;
|
2000-10-09 12:16:27 +00:00
|
|
|
item.pszText = buffer;
|
|
|
|
item.cchTextMax = sizeof(buffer);
|
2003-03-05 22:07:40 +00:00
|
|
|
item.mask = TVIF_TEXT | TVIF_PARAM;
|
2001-05-06 14:35:20 +00:00
|
|
|
TreeView_GetItem(((LPNMHDR) lParam)->hwndFrom, &item);
|
2003-03-05 22:07:40 +00:00
|
|
|
{
|
|
|
|
/* Destroy all controls in the currently visible panel. */
|
|
|
|
int k;
|
|
|
|
HWND item;
|
|
|
|
struct winctrl *c;
|
|
|
|
|
|
|
|
while ((c = winctrl_findbyindex(&ctrls_panel, 0)) != NULL) {
|
|
|
|
for (k = 0; k < c->num_ids; k++) {
|
|
|
|
item = GetDlgItem(hwnd, c->base_id + k);
|
|
|
|
if (item)
|
|
|
|
DestroyWindow(item);
|
|
|
|
}
|
|
|
|
winctrl_rem_shortcuts(&dp, c);
|
|
|
|
winctrl_remove(&ctrls_panel, c);
|
|
|
|
sfree(c->data);
|
|
|
|
sfree(c);
|
|
|
|
}
|
2001-05-06 14:35:20 +00:00
|
|
|
}
|
2003-03-05 22:07:40 +00:00
|
|
|
create_controls(hwnd, (char *)item.lParam);
|
|
|
|
|
|
|
|
dlg_refresh(NULL, &dp); /* set up control values */
|
2001-09-07 21:07:15 +00:00
|
|
|
|
|
|
|
SendMessage (hwnd, WM_SETREDRAW, TRUE, 0);
|
|
|
|
InvalidateRect (hwnd, NULL, TRUE);
|
2000-10-09 12:16:27 +00:00
|
|
|
|
2001-05-06 14:35:20 +00:00
|
|
|
SetFocus(((LPNMHDR) lParam)->hwndFrom); /* ensure focus stays */
|
2000-10-09 12:16:27 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
break;
|
1999-01-08 13:02:13 +00:00
|
|
|
case WM_COMMAND:
|
2003-03-05 22:07:40 +00:00
|
|
|
case WM_DRAWITEM:
|
|
|
|
default: /* also handle drag list msg here */
|
2000-10-09 12:16:27 +00:00
|
|
|
/*
|
|
|
|
* Only process WM_COMMAND once the dialog is fully formed.
|
|
|
|
*/
|
2005-05-21 14:16:43 +00:00
|
|
|
if (GetWindowLongPtr(hwnd, GWLP_USERDATA) == 1) {
|
2003-03-05 22:07:40 +00:00
|
|
|
ret = winctrl_handle_command(&dp, msg, wParam, lParam);
|
|
|
|
if (dp.ended && GetCapture() != hwnd)
|
2003-06-16 23:55:26 +00:00
|
|
|
SaneEndDialog(hwnd, dp.endresult ? 1 : 0);
|
2003-03-05 22:07:40 +00:00
|
|
|
} else
|
|
|
|
ret = 0;
|
|
|
|
return ret;
|
2001-12-06 13:28:02 +00:00
|
|
|
case WM_HELP:
|
2006-12-17 11:16:07 +00:00
|
|
|
if (!winctrl_context_help(&dp, hwnd,
|
|
|
|
((LPHELPINFO)lParam)->iCtrlId))
|
|
|
|
MessageBeep(0);
|
2001-12-06 13:28:02 +00:00
|
|
|
break;
|
1999-01-08 13:02:13 +00:00
|
|
|
case WM_CLOSE:
|
2006-12-17 11:16:07 +00:00
|
|
|
quit_help(hwnd);
|
2003-06-16 23:55:26 +00:00
|
|
|
SaneEndDialog(hwnd, 0);
|
1999-01-08 13:02:13 +00:00
|
|
|
return 0;
|
2000-07-26 12:13:51 +00:00
|
|
|
|
|
|
|
/* Grrr Explorer will maximize Dialogs! */
|
|
|
|
case WM_SIZE:
|
|
|
|
if (wParam == SIZE_MAXIMIZED)
|
2001-05-06 14:35:20 +00:00
|
|
|
force_normal(hwnd);
|
2000-07-26 12:13:51 +00:00
|
|
|
return 0;
|
2001-08-25 19:33:33 +00:00
|
|
|
|
1999-01-08 13:02:13 +00:00
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2003-03-05 22:07:40 +00:00
|
|
|
void modal_about_box(HWND hwnd)
|
2001-05-06 14:35:20 +00:00
|
|
|
{
|
2003-03-05 22:07:40 +00:00
|
|
|
EnableWindow(hwnd, 0);
|
|
|
|
DialogBox(hinst, MAKEINTRESOURCE(IDD_ABOUTBOX), hwnd, AboutProc);
|
|
|
|
EnableWindow(hwnd, 1);
|
|
|
|
SetActiveWindow(hwnd);
|
1999-01-08 13:02:13 +00:00
|
|
|
}
|
|
|
|
|
2003-03-05 22:07:40 +00:00
|
|
|
void show_help(HWND hwnd)
|
2001-05-06 14:35:20 +00:00
|
|
|
{
|
2006-12-17 11:16:07 +00:00
|
|
|
launch_help(hwnd, NULL);
|
1999-01-08 13:02:13 +00:00
|
|
|
}
|
|
|
|
|
2001-05-06 14:35:20 +00:00
|
|
|
void defuse_showwindow(void)
|
|
|
|
{
|
2000-10-12 12:56:33 +00:00
|
|
|
/*
|
|
|
|
* Work around the fact that the app's first call to ShowWindow
|
|
|
|
* will ignore the default in favour of the shell-provided
|
|
|
|
* setting.
|
|
|
|
*/
|
|
|
|
{
|
2001-05-06 14:35:20 +00:00
|
|
|
HWND hwnd;
|
|
|
|
hwnd = CreateDialog(hinst, MAKEINTRESOURCE(IDD_ABOUTBOX),
|
|
|
|
NULL, NullDlgProc);
|
|
|
|
ShowWindow(hwnd, SW_HIDE);
|
2001-05-19 15:23:12 +00:00
|
|
|
SetActiveWindow(hwnd);
|
2001-05-06 14:35:20 +00:00
|
|
|
DestroyWindow(hwnd);
|
2000-10-12 12:56:33 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2001-05-06 14:35:20 +00:00
|
|
|
int do_config(void)
|
|
|
|
{
|
1999-01-08 13:02:13 +00:00
|
|
|
int ret;
|
|
|
|
|
2003-03-05 22:07:40 +00:00
|
|
|
ctrlbox = ctrl_new_box();
|
2005-04-07 01:36:28 +00:00
|
|
|
setup_config_box(ctrlbox, FALSE, 0, 0);
|
2006-12-17 11:16:07 +00:00
|
|
|
win_setup_config_box(ctrlbox, &dp.hwnd, has_help(), FALSE, 0);
|
2003-03-08 11:46:42 +00:00
|
|
|
dp_init(&dp);
|
2003-03-05 22:07:40 +00:00
|
|
|
winctrl_init(&ctrls_base);
|
|
|
|
winctrl_init(&ctrls_panel);
|
2003-03-08 11:46:42 +00:00
|
|
|
dp_add_tree(&dp, &ctrls_base);
|
|
|
|
dp_add_tree(&dp, &ctrls_panel);
|
2003-04-06 14:11:33 +00:00
|
|
|
dp.wintitle = dupprintf("%s Configuration", appname);
|
|
|
|
dp.errtitle = dupprintf("%s Error", appname);
|
Post-release destabilisation! Completely remove the struct type
'Config' in putty.h, which stores all PuTTY's settings and includes an
arbitrary length limit on every single one of those settings which is
stored in string form. In place of it is 'Conf', an opaque data type
everywhere outside the new file conf.c, which stores a list of (key,
value) pairs in which every key contains an integer identifying a
configuration setting, and for some of those integers the key also
contains extra parts (so that, for instance, CONF_environmt is a
string-to-string mapping). Everywhere that a Config was previously
used, a Conf is now; everywhere there was a Config structure copy,
conf_copy() is called; every lookup, adjustment, load and save
operation on a Config has been rewritten; and there's a mechanism for
serialising a Conf into a binary blob and back for use with Duplicate
Session.
User-visible effects of this change _should_ be minimal, though I
don't doubt I've introduced one or two bugs here and there which will
eventually be found. The _intended_ visible effects of this change are
that all arbitrary limits on configuration strings and lists (e.g.
limit on number of port forwardings) should now disappear; that list
boxes in the configuration will now be displayed in a sorted order
rather than the arbitrary order in which they were added to the list
(since the underlying data structure is now a sorted tree234 rather
than an ad-hoc comma-separated string); and one more specific change,
which is that local and dynamic port forwardings on the same port
number are now mutually exclusive in the configuration (putting 'D' in
the key rather than the value was a mistake in the first place).
One other reorganisation as a result of this is that I've moved all
the dialog.c standard handlers (dlg_stdeditbox_handler and friends)
out into config.c, because I can't really justify calling them generic
any more. When they took a pointer to an arbitrary structure type and
the offset of a field within that structure, they were independent of
whether that structure was a Config or something completely different,
but now they really do expect to talk to a Conf, which can _only_ be
used for PuTTY configuration, so I've renamed them all things like
conf_editbox_handler and moved them out of the nominally independent
dialog-box management module into the PuTTY-specific config.c.
[originally from svn r9214]
2011-07-14 18:52:21 +00:00
|
|
|
dp.data = conf;
|
2010-12-29 14:11:25 +00:00
|
|
|
dlg_auto_set_fixed_pitch_flag(&dp);
|
2003-03-05 22:07:40 +00:00
|
|
|
dp.shortcuts['g'] = TRUE; /* the treeview: `Cate&gory' */
|
|
|
|
|
2001-05-06 14:35:20 +00:00
|
|
|
ret =
|
2003-06-16 23:55:26 +00:00
|
|
|
SaneDialogBox(hinst, MAKEINTRESOURCE(IDD_MAINBOX), NULL,
|
2003-03-05 22:07:40 +00:00
|
|
|
GenericMainDlgProc);
|
1999-01-08 13:02:13 +00:00
|
|
|
|
2003-03-05 22:07:40 +00:00
|
|
|
ctrl_free_box(ctrlbox);
|
|
|
|
winctrl_cleanup(&ctrls_panel);
|
2003-03-08 11:46:42 +00:00
|
|
|
winctrl_cleanup(&ctrls_base);
|
|
|
|
dp_cleanup(&dp);
|
2003-03-05 22:07:40 +00:00
|
|
|
|
1999-01-08 13:02:13 +00:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2004-12-29 12:32:25 +00:00
|
|
|
int do_reconfig(HWND hwnd, int protcfginfo)
|
2001-05-06 14:35:20 +00:00
|
|
|
{
|
Post-release destabilisation! Completely remove the struct type
'Config' in putty.h, which stores all PuTTY's settings and includes an
arbitrary length limit on every single one of those settings which is
stored in string form. In place of it is 'Conf', an opaque data type
everywhere outside the new file conf.c, which stores a list of (key,
value) pairs in which every key contains an integer identifying a
configuration setting, and for some of those integers the key also
contains extra parts (so that, for instance, CONF_environmt is a
string-to-string mapping). Everywhere that a Config was previously
used, a Conf is now; everywhere there was a Config structure copy,
conf_copy() is called; every lookup, adjustment, load and save
operation on a Config has been rewritten; and there's a mechanism for
serialising a Conf into a binary blob and back for use with Duplicate
Session.
User-visible effects of this change _should_ be minimal, though I
don't doubt I've introduced one or two bugs here and there which will
eventually be found. The _intended_ visible effects of this change are
that all arbitrary limits on configuration strings and lists (e.g.
limit on number of port forwardings) should now disappear; that list
boxes in the configuration will now be displayed in a sorted order
rather than the arbitrary order in which they were added to the list
(since the underlying data structure is now a sorted tree234 rather
than an ad-hoc comma-separated string); and one more specific change,
which is that local and dynamic port forwardings on the same port
number are now mutually exclusive in the configuration (putting 'D' in
the key rather than the value was a mistake in the first place).
One other reorganisation as a result of this is that I've moved all
the dialog.c standard handlers (dlg_stdeditbox_handler and friends)
out into config.c, because I can't really justify calling them generic
any more. When they took a pointer to an arbitrary structure type and
the offset of a field within that structure, they were independent of
whether that structure was a Config or something completely different,
but now they really do expect to talk to a Conf, which can _only_ be
used for PuTTY configuration, so I've renamed them all things like
conf_editbox_handler and moved them out of the nominally independent
dialog-box management module into the PuTTY-specific config.c.
[originally from svn r9214]
2011-07-14 18:52:21 +00:00
|
|
|
Conf *backup_conf;
|
|
|
|
int ret, protocol;
|
1999-01-08 13:02:13 +00:00
|
|
|
|
Post-release destabilisation! Completely remove the struct type
'Config' in putty.h, which stores all PuTTY's settings and includes an
arbitrary length limit on every single one of those settings which is
stored in string form. In place of it is 'Conf', an opaque data type
everywhere outside the new file conf.c, which stores a list of (key,
value) pairs in which every key contains an integer identifying a
configuration setting, and for some of those integers the key also
contains extra parts (so that, for instance, CONF_environmt is a
string-to-string mapping). Everywhere that a Config was previously
used, a Conf is now; everywhere there was a Config structure copy,
conf_copy() is called; every lookup, adjustment, load and save
operation on a Config has been rewritten; and there's a mechanism for
serialising a Conf into a binary blob and back for use with Duplicate
Session.
User-visible effects of this change _should_ be minimal, though I
don't doubt I've introduced one or two bugs here and there which will
eventually be found. The _intended_ visible effects of this change are
that all arbitrary limits on configuration strings and lists (e.g.
limit on number of port forwardings) should now disappear; that list
boxes in the configuration will now be displayed in a sorted order
rather than the arbitrary order in which they were added to the list
(since the underlying data structure is now a sorted tree234 rather
than an ad-hoc comma-separated string); and one more specific change,
which is that local and dynamic port forwardings on the same port
number are now mutually exclusive in the configuration (putting 'D' in
the key rather than the value was a mistake in the first place).
One other reorganisation as a result of this is that I've moved all
the dialog.c standard handlers (dlg_stdeditbox_handler and friends)
out into config.c, because I can't really justify calling them generic
any more. When they took a pointer to an arbitrary structure type and
the offset of a field within that structure, they were independent of
whether that structure was a Config or something completely different,
but now they really do expect to talk to a Conf, which can _only_ be
used for PuTTY configuration, so I've renamed them all things like
conf_editbox_handler and moved them out of the nominally independent
dialog-box management module into the PuTTY-specific config.c.
[originally from svn r9214]
2011-07-14 18:52:21 +00:00
|
|
|
backup_conf = conf_copy(conf);
|
2003-03-05 22:07:40 +00:00
|
|
|
|
|
|
|
ctrlbox = ctrl_new_box();
|
Post-release destabilisation! Completely remove the struct type
'Config' in putty.h, which stores all PuTTY's settings and includes an
arbitrary length limit on every single one of those settings which is
stored in string form. In place of it is 'Conf', an opaque data type
everywhere outside the new file conf.c, which stores a list of (key,
value) pairs in which every key contains an integer identifying a
configuration setting, and for some of those integers the key also
contains extra parts (so that, for instance, CONF_environmt is a
string-to-string mapping). Everywhere that a Config was previously
used, a Conf is now; everywhere there was a Config structure copy,
conf_copy() is called; every lookup, adjustment, load and save
operation on a Config has been rewritten; and there's a mechanism for
serialising a Conf into a binary blob and back for use with Duplicate
Session.
User-visible effects of this change _should_ be minimal, though I
don't doubt I've introduced one or two bugs here and there which will
eventually be found. The _intended_ visible effects of this change are
that all arbitrary limits on configuration strings and lists (e.g.
limit on number of port forwardings) should now disappear; that list
boxes in the configuration will now be displayed in a sorted order
rather than the arbitrary order in which they were added to the list
(since the underlying data structure is now a sorted tree234 rather
than an ad-hoc comma-separated string); and one more specific change,
which is that local and dynamic port forwardings on the same port
number are now mutually exclusive in the configuration (putting 'D' in
the key rather than the value was a mistake in the first place).
One other reorganisation as a result of this is that I've moved all
the dialog.c standard handlers (dlg_stdeditbox_handler and friends)
out into config.c, because I can't really justify calling them generic
any more. When they took a pointer to an arbitrary structure type and
the offset of a field within that structure, they were independent of
whether that structure was a Config or something completely different,
but now they really do expect to talk to a Conf, which can _only_ be
used for PuTTY configuration, so I've renamed them all things like
conf_editbox_handler and moved them out of the nominally independent
dialog-box management module into the PuTTY-specific config.c.
[originally from svn r9214]
2011-07-14 18:52:21 +00:00
|
|
|
protocol = conf_get_int(conf, CONF_protocol);
|
|
|
|
setup_config_box(ctrlbox, TRUE, protocol, protcfginfo);
|
|
|
|
win_setup_config_box(ctrlbox, &dp.hwnd, has_help(), TRUE, protocol);
|
2003-03-08 11:46:42 +00:00
|
|
|
dp_init(&dp);
|
2003-03-05 22:07:40 +00:00
|
|
|
winctrl_init(&ctrls_base);
|
|
|
|
winctrl_init(&ctrls_panel);
|
2003-03-08 11:46:42 +00:00
|
|
|
dp_add_tree(&dp, &ctrls_base);
|
|
|
|
dp_add_tree(&dp, &ctrls_panel);
|
2003-04-06 14:11:33 +00:00
|
|
|
dp.wintitle = dupprintf("%s Reconfiguration", appname);
|
|
|
|
dp.errtitle = dupprintf("%s Error", appname);
|
Post-release destabilisation! Completely remove the struct type
'Config' in putty.h, which stores all PuTTY's settings and includes an
arbitrary length limit on every single one of those settings which is
stored in string form. In place of it is 'Conf', an opaque data type
everywhere outside the new file conf.c, which stores a list of (key,
value) pairs in which every key contains an integer identifying a
configuration setting, and for some of those integers the key also
contains extra parts (so that, for instance, CONF_environmt is a
string-to-string mapping). Everywhere that a Config was previously
used, a Conf is now; everywhere there was a Config structure copy,
conf_copy() is called; every lookup, adjustment, load and save
operation on a Config has been rewritten; and there's a mechanism for
serialising a Conf into a binary blob and back for use with Duplicate
Session.
User-visible effects of this change _should_ be minimal, though I
don't doubt I've introduced one or two bugs here and there which will
eventually be found. The _intended_ visible effects of this change are
that all arbitrary limits on configuration strings and lists (e.g.
limit on number of port forwardings) should now disappear; that list
boxes in the configuration will now be displayed in a sorted order
rather than the arbitrary order in which they were added to the list
(since the underlying data structure is now a sorted tree234 rather
than an ad-hoc comma-separated string); and one more specific change,
which is that local and dynamic port forwardings on the same port
number are now mutually exclusive in the configuration (putting 'D' in
the key rather than the value was a mistake in the first place).
One other reorganisation as a result of this is that I've moved all
the dialog.c standard handlers (dlg_stdeditbox_handler and friends)
out into config.c, because I can't really justify calling them generic
any more. When they took a pointer to an arbitrary structure type and
the offset of a field within that structure, they were independent of
whether that structure was a Config or something completely different,
but now they really do expect to talk to a Conf, which can _only_ be
used for PuTTY configuration, so I've renamed them all things like
conf_editbox_handler and moved them out of the nominally independent
dialog-box management module into the PuTTY-specific config.c.
[originally from svn r9214]
2011-07-14 18:52:21 +00:00
|
|
|
dp.data = conf;
|
2010-12-29 14:11:25 +00:00
|
|
|
dlg_auto_set_fixed_pitch_flag(&dp);
|
2003-03-05 22:07:40 +00:00
|
|
|
dp.shortcuts['g'] = TRUE; /* the treeview: `Cate&gory' */
|
|
|
|
|
2003-06-16 23:55:26 +00:00
|
|
|
ret = SaneDialogBox(hinst, MAKEINTRESOURCE(IDD_MAINBOX), NULL,
|
2003-03-05 22:07:40 +00:00
|
|
|
GenericMainDlgProc);
|
|
|
|
|
|
|
|
ctrl_free_box(ctrlbox);
|
|
|
|
winctrl_cleanup(&ctrls_base);
|
|
|
|
winctrl_cleanup(&ctrls_panel);
|
2003-03-08 11:46:42 +00:00
|
|
|
dp_cleanup(&dp);
|
2003-03-05 22:07:40 +00:00
|
|
|
|
1999-01-08 13:02:13 +00:00
|
|
|
if (!ret)
|
Post-release destabilisation! Completely remove the struct type
'Config' in putty.h, which stores all PuTTY's settings and includes an
arbitrary length limit on every single one of those settings which is
stored in string form. In place of it is 'Conf', an opaque data type
everywhere outside the new file conf.c, which stores a list of (key,
value) pairs in which every key contains an integer identifying a
configuration setting, and for some of those integers the key also
contains extra parts (so that, for instance, CONF_environmt is a
string-to-string mapping). Everywhere that a Config was previously
used, a Conf is now; everywhere there was a Config structure copy,
conf_copy() is called; every lookup, adjustment, load and save
operation on a Config has been rewritten; and there's a mechanism for
serialising a Conf into a binary blob and back for use with Duplicate
Session.
User-visible effects of this change _should_ be minimal, though I
don't doubt I've introduced one or two bugs here and there which will
eventually be found. The _intended_ visible effects of this change are
that all arbitrary limits on configuration strings and lists (e.g.
limit on number of port forwardings) should now disappear; that list
boxes in the configuration will now be displayed in a sorted order
rather than the arbitrary order in which they were added to the list
(since the underlying data structure is now a sorted tree234 rather
than an ad-hoc comma-separated string); and one more specific change,
which is that local and dynamic port forwardings on the same port
number are now mutually exclusive in the configuration (putting 'D' in
the key rather than the value was a mistake in the first place).
One other reorganisation as a result of this is that I've moved all
the dialog.c standard handlers (dlg_stdeditbox_handler and friends)
out into config.c, because I can't really justify calling them generic
any more. When they took a pointer to an arbitrary structure type and
the offset of a field within that structure, they were independent of
whether that structure was a Config or something completely different,
but now they really do expect to talk to a Conf, which can _only_ be
used for PuTTY configuration, so I've renamed them all things like
conf_editbox_handler and moved them out of the nominally independent
dialog-box management module into the PuTTY-specific config.c.
[originally from svn r9214]
2011-07-14 18:52:21 +00:00
|
|
|
conf_copy_into(conf, backup_conf);
|
|
|
|
|
|
|
|
conf_free(backup_conf);
|
2000-07-26 12:13:51 +00:00
|
|
|
|
1999-01-08 13:02:13 +00:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2003-05-04 14:18:18 +00:00
|
|
|
void logevent(void *frontend, const char *string)
|
2001-05-06 14:35:20 +00:00
|
|
|
{
|
2001-02-27 17:02:51 +00:00
|
|
|
char timebuf[40];
|
Don't grow logevent buf indefinitely
The PuTTY GUIs (Unix and Windows) maintain an in-memory event log
for display to users as they request. This uses ints for tracking
eventlog size, which is subject to memory exhaustion and (given
enough heap space) overflow attacks by servers (via, e.g., constant
rekeying).
Also a bounded log is more user-friendly. It is rare to want more
than the initial logging and the logging from a few recent rekey
events.
The Windows fix has been tested using Dr. Memory as a valgrind
substitute. No errors corresponding to the affected code showed up.
The Dr. Memory results.txt was split into a file per-error and then
grep Error $(grep -l windlg *)|cut -d: -f3-|sort |uniq -c
was used to compare. Differences arose from different usage of the GUI,
but no error could be traced to the code modified in this commit.
The Unix fix has been tested using valgrind. We don't destroy the
eventlog_stuff eventlog arrays, so we can't be entirely sure that we
don't leak more than we did before, but from code inspection it looks
like we don't (and anyways, if we leaked as much as before, just without
the integer overflow, well, that's still an improvement).
2013-07-22 23:09:04 +00:00
|
|
|
char **location;
|
2005-01-09 14:27:48 +00:00
|
|
|
struct tm tm;
|
2001-02-27 17:02:51 +00:00
|
|
|
|
2002-10-26 12:58:13 +00:00
|
|
|
log_eventlog(logctx, string);
|
2002-09-15 13:21:32 +00:00
|
|
|
|
2005-01-09 14:27:48 +00:00
|
|
|
tm=ltime();
|
|
|
|
strftime(timebuf, sizeof(timebuf), "%Y-%m-%d %H:%M:%S\t", &tm);
|
2001-02-27 17:02:51 +00:00
|
|
|
|
Don't grow logevent buf indefinitely
The PuTTY GUIs (Unix and Windows) maintain an in-memory event log
for display to users as they request. This uses ints for tracking
eventlog size, which is subject to memory exhaustion and (given
enough heap space) overflow attacks by servers (via, e.g., constant
rekeying).
Also a bounded log is more user-friendly. It is rare to want more
than the initial logging and the logging from a few recent rekey
events.
The Windows fix has been tested using Dr. Memory as a valgrind
substitute. No errors corresponding to the affected code showed up.
The Dr. Memory results.txt was split into a file per-error and then
grep Error $(grep -l windlg *)|cut -d: -f3-|sort |uniq -c
was used to compare. Differences arose from different usage of the GUI,
but no error could be traced to the code modified in this commit.
The Unix fix has been tested using valgrind. We don't destroy the
eventlog_stuff eventlog arrays, so we can't be entirely sure that we
don't leak more than we did before, but from code inspection it looks
like we don't (and anyways, if we leaked as much as before, just without
the integer overflow, well, that's still an improvement).
2013-07-22 23:09:04 +00:00
|
|
|
if (ninitial < LOGEVENT_INITIAL_MAX)
|
|
|
|
location = &events_initial[ninitial];
|
|
|
|
else
|
|
|
|
location = &events_circular[(circular_first + ncircular) % LOGEVENT_CIRCULAR_MAX];
|
|
|
|
|
|
|
|
if (*location)
|
|
|
|
sfree(*location);
|
2018-02-13 19:45:54 +00:00
|
|
|
*location = dupcat(timebuf, string, (const char *)NULL);
|
2000-09-22 14:24:27 +00:00
|
|
|
if (logbox) {
|
2001-05-06 14:35:20 +00:00
|
|
|
int count;
|
|
|
|
SendDlgItemMessage(logbox, IDN_LIST, LB_ADDSTRING,
|
Don't grow logevent buf indefinitely
The PuTTY GUIs (Unix and Windows) maintain an in-memory event log
for display to users as they request. This uses ints for tracking
eventlog size, which is subject to memory exhaustion and (given
enough heap space) overflow attacks by servers (via, e.g., constant
rekeying).
Also a bounded log is more user-friendly. It is rare to want more
than the initial logging and the logging from a few recent rekey
events.
The Windows fix has been tested using Dr. Memory as a valgrind
substitute. No errors corresponding to the affected code showed up.
The Dr. Memory results.txt was split into a file per-error and then
grep Error $(grep -l windlg *)|cut -d: -f3-|sort |uniq -c
was used to compare. Differences arose from different usage of the GUI,
but no error could be traced to the code modified in this commit.
The Unix fix has been tested using valgrind. We don't destroy the
eventlog_stuff eventlog arrays, so we can't be entirely sure that we
don't leak more than we did before, but from code inspection it looks
like we don't (and anyways, if we leaked as much as before, just without
the integer overflow, well, that's still an improvement).
2013-07-22 23:09:04 +00:00
|
|
|
0, (LPARAM) *location);
|
2001-05-06 14:35:20 +00:00
|
|
|
count = SendDlgItemMessage(logbox, IDN_LIST, LB_GETCOUNT, 0, 0);
|
|
|
|
SendDlgItemMessage(logbox, IDN_LIST, LB_SETTOPINDEX, count - 1, 0);
|
2000-09-22 14:24:27 +00:00
|
|
|
}
|
Don't grow logevent buf indefinitely
The PuTTY GUIs (Unix and Windows) maintain an in-memory event log
for display to users as they request. This uses ints for tracking
eventlog size, which is subject to memory exhaustion and (given
enough heap space) overflow attacks by servers (via, e.g., constant
rekeying).
Also a bounded log is more user-friendly. It is rare to want more
than the initial logging and the logging from a few recent rekey
events.
The Windows fix has been tested using Dr. Memory as a valgrind
substitute. No errors corresponding to the affected code showed up.
The Dr. Memory results.txt was split into a file per-error and then
grep Error $(grep -l windlg *)|cut -d: -f3-|sort |uniq -c
was used to compare. Differences arose from different usage of the GUI,
but no error could be traced to the code modified in this commit.
The Unix fix has been tested using valgrind. We don't destroy the
eventlog_stuff eventlog arrays, so we can't be entirely sure that we
don't leak more than we did before, but from code inspection it looks
like we don't (and anyways, if we leaked as much as before, just without
the integer overflow, well, that's still an improvement).
2013-07-22 23:09:04 +00:00
|
|
|
if (ninitial < LOGEVENT_INITIAL_MAX) {
|
|
|
|
ninitial++;
|
|
|
|
} else if (ncircular < LOGEVENT_CIRCULAR_MAX) {
|
|
|
|
ncircular++;
|
|
|
|
} else if (ncircular == LOGEVENT_CIRCULAR_MAX) {
|
|
|
|
circular_first = (circular_first + 1) % LOGEVENT_CIRCULAR_MAX;
|
|
|
|
sfree(events_circular[circular_first]);
|
|
|
|
events_circular[circular_first] = dupstr("..");
|
|
|
|
}
|
1999-01-08 13:02:13 +00:00
|
|
|
}
|
|
|
|
|
2001-05-06 14:35:20 +00:00
|
|
|
void showeventlog(HWND hwnd)
|
|
|
|
{
|
1999-01-08 13:02:13 +00:00
|
|
|
if (!logbox) {
|
2001-05-06 14:35:20 +00:00
|
|
|
logbox = CreateDialog(hinst, MAKEINTRESOURCE(IDD_LOGBOX),
|
|
|
|
hwnd, LogProc);
|
|
|
|
ShowWindow(logbox, SW_SHOWNORMAL);
|
1999-01-08 13:02:13 +00:00
|
|
|
}
|
2001-01-23 17:40:51 +00:00
|
|
|
SetActiveWindow(logbox);
|
1999-01-08 13:02:13 +00:00
|
|
|
}
|
|
|
|
|
2001-05-06 14:35:20 +00:00
|
|
|
void showabout(HWND hwnd)
|
|
|
|
{
|
|
|
|
DialogBox(hinst, MAKEINTRESOURCE(IDD_ABOUTBOX), hwnd, AboutProc);
|
1999-01-08 13:02:13 +00:00
|
|
|
}
|
|
|
|
|
2015-05-15 09:12:06 +00:00
|
|
|
int verify_ssh_host_key(void *frontend, char *host, int port,
|
|
|
|
const char *keytype, char *keystr, char *fingerprint,
|
2005-02-17 18:34:24 +00:00
|
|
|
void (*callback)(void *ctx, int result), void *ctx)
|
2001-05-06 14:35:20 +00:00
|
|
|
{
|
2000-09-27 15:21:04 +00:00
|
|
|
int ret;
|
1999-01-08 13:02:13 +00:00
|
|
|
|
2000-09-27 15:21:04 +00:00
|
|
|
static const char absentmsg[] =
|
2001-05-06 14:35:20 +00:00
|
|
|
"The server's host key is not cached in the registry. You\n"
|
|
|
|
"have no guarantee that the server is the computer you\n"
|
|
|
|
"think it is.\n"
|
2003-06-26 14:19:33 +00:00
|
|
|
"The server's %s key fingerprint is:\n"
|
2001-05-06 14:35:20 +00:00
|
|
|
"%s\n"
|
|
|
|
"If you trust this host, hit Yes to add the key to\n"
|
2003-04-06 14:11:33 +00:00
|
|
|
"%s's cache and carry on connecting.\n"
|
2001-05-13 14:11:49 +00:00
|
|
|
"If you want to carry on connecting just once, without\n"
|
|
|
|
"adding the key to the cache, hit No.\n"
|
|
|
|
"If you do not trust this host, hit Cancel to abandon the\n"
|
2001-05-06 14:35:20 +00:00
|
|
|
"connection.\n";
|
2000-09-27 15:21:04 +00:00
|
|
|
|
|
|
|
static const char wrongmsg[] =
|
2001-05-06 14:35:20 +00:00
|
|
|
"WARNING - POTENTIAL SECURITY BREACH!\n"
|
|
|
|
"\n"
|
2003-04-06 14:11:33 +00:00
|
|
|
"The server's host key does not match the one %s has\n"
|
2001-05-06 14:35:20 +00:00
|
|
|
"cached in the registry. This means that either the\n"
|
|
|
|
"server administrator has changed the host key, or you\n"
|
|
|
|
"have actually connected to another computer pretending\n"
|
|
|
|
"to be the server.\n"
|
2003-06-26 14:19:33 +00:00
|
|
|
"The new %s key fingerprint is:\n"
|
2001-05-06 14:35:20 +00:00
|
|
|
"%s\n"
|
|
|
|
"If you were expecting this change and trust the new key,\n"
|
2003-04-06 14:11:33 +00:00
|
|
|
"hit Yes to update %s's cache and continue connecting.\n"
|
2001-05-06 14:35:20 +00:00
|
|
|
"If you want to carry on connecting but without updating\n"
|
|
|
|
"the cache, hit No.\n"
|
|
|
|
"If you want to abandon the connection completely, hit\n"
|
|
|
|
"Cancel. Hitting Cancel is the ONLY guaranteed safe\n" "choice.\n";
|
2000-09-27 15:21:04 +00:00
|
|
|
|
2003-04-06 14:11:33 +00:00
|
|
|
static const char mbtitle[] = "%s Security Alert";
|
2000-09-25 15:47:57 +00:00
|
|
|
|
|
|
|
/*
|
2000-09-27 15:21:04 +00:00
|
|
|
* Verify the key against the registry.
|
2000-09-25 15:47:57 +00:00
|
|
|
*/
|
2000-09-28 08:37:10 +00:00
|
|
|
ret = verify_host_key(host, port, keytype, keystr);
|
2000-09-27 15:21:04 +00:00
|
|
|
|
2001-05-06 14:35:20 +00:00
|
|
|
if (ret == 0) /* success - key matched OK */
|
2005-02-17 18:34:24 +00:00
|
|
|
return 1;
|
2009-01-06 00:25:07 +00:00
|
|
|
else if (ret == 2) { /* key was different */
|
2001-05-06 14:35:20 +00:00
|
|
|
int mbret;
|
2005-03-01 00:00:09 +00:00
|
|
|
char *text = dupprintf(wrongmsg, appname, keytype, fingerprint,
|
|
|
|
appname);
|
|
|
|
char *caption = dupprintf(mbtitle, appname);
|
|
|
|
mbret = message_box(text, caption,
|
|
|
|
MB_ICONWARNING | MB_YESNOCANCEL | MB_DEFBUTTON3,
|
|
|
|
HELPCTXID(errors_hostkey_changed));
|
2005-02-20 23:00:17 +00:00
|
|
|
assert(mbret==IDYES || mbret==IDNO || mbret==IDCANCEL);
|
2005-03-01 00:00:09 +00:00
|
|
|
sfree(text);
|
|
|
|
sfree(caption);
|
2005-02-21 23:34:41 +00:00
|
|
|
if (mbret == IDYES) {
|
2001-05-06 14:35:20 +00:00
|
|
|
store_host_key(host, port, keytype, keystr);
|
2005-02-21 23:34:41 +00:00
|
|
|
return 1;
|
|
|
|
} else if (mbret == IDNO)
|
2005-02-20 23:00:17 +00:00
|
|
|
return 1;
|
2009-01-06 00:25:07 +00:00
|
|
|
} else if (ret == 1) { /* key was absent */
|
2001-05-06 14:35:20 +00:00
|
|
|
int mbret;
|
2005-03-01 00:00:09 +00:00
|
|
|
char *text = dupprintf(absentmsg, keytype, fingerprint, appname);
|
|
|
|
char *caption = dupprintf(mbtitle, appname);
|
|
|
|
mbret = message_box(text, caption,
|
|
|
|
MB_ICONWARNING | MB_YESNOCANCEL | MB_DEFBUTTON3,
|
|
|
|
HELPCTXID(errors_hostkey_absent));
|
2005-02-20 23:00:17 +00:00
|
|
|
assert(mbret==IDYES || mbret==IDNO || mbret==IDCANCEL);
|
2005-03-01 00:00:09 +00:00
|
|
|
sfree(text);
|
|
|
|
sfree(caption);
|
|
|
|
if (mbret == IDYES) {
|
2001-05-13 14:11:49 +00:00
|
|
|
store_host_key(host, port, keytype, keystr);
|
2005-03-01 00:00:09 +00:00
|
|
|
return 1;
|
|
|
|
} else if (mbret == IDNO)
|
2005-02-20 23:00:17 +00:00
|
|
|
return 1;
|
2000-09-25 15:47:57 +00:00
|
|
|
}
|
2009-01-06 00:25:07 +00:00
|
|
|
return 0; /* abandon the connection */
|
2000-09-25 15:47:57 +00:00
|
|
|
}
|
2001-01-07 18:24:59 +00:00
|
|
|
|
2001-08-25 19:33:33 +00:00
|
|
|
/*
|
2004-12-23 02:24:07 +00:00
|
|
|
* Ask whether the selected algorithm is acceptable (since it was
|
2001-08-25 19:33:33 +00:00
|
|
|
* below the configured 'warn' threshold).
|
|
|
|
*/
|
2005-02-17 18:34:24 +00:00
|
|
|
int askalg(void *frontend, const char *algtype, const char *algname,
|
|
|
|
void (*callback)(void *ctx, int result), void *ctx)
|
2001-08-25 19:33:33 +00:00
|
|
|
{
|
2003-04-06 14:11:33 +00:00
|
|
|
static const char mbtitle[] = "%s Security Alert";
|
2001-08-25 19:33:33 +00:00
|
|
|
static const char msg[] =
|
2004-12-23 02:24:07 +00:00
|
|
|
"The first %s supported by the server\n"
|
2001-08-25 19:33:33 +00:00
|
|
|
"is %.64s, which is below the configured\n"
|
|
|
|
"warning threshold.\n"
|
|
|
|
"Do you want to continue with this connection?\n";
|
2003-04-06 14:11:33 +00:00
|
|
|
char *message, *title;
|
2001-08-25 19:33:33 +00:00
|
|
|
int mbret;
|
|
|
|
|
2004-12-23 02:24:07 +00:00
|
|
|
message = dupprintf(msg, algtype, algname);
|
2003-04-06 14:11:33 +00:00
|
|
|
title = dupprintf(mbtitle, appname);
|
|
|
|
mbret = MessageBox(NULL, message, title,
|
2005-02-15 19:22:47 +00:00
|
|
|
MB_ICONWARNING | MB_YESNO | MB_DEFBUTTON2);
|
2007-01-08 19:38:39 +00:00
|
|
|
socket_reselect_all();
|
2003-04-06 14:11:33 +00:00
|
|
|
sfree(message);
|
|
|
|
sfree(title);
|
2001-08-25 19:33:33 +00:00
|
|
|
if (mbret == IDYES)
|
2005-02-17 18:34:24 +00:00
|
|
|
return 1;
|
2001-08-25 19:33:33 +00:00
|
|
|
else
|
2005-02-17 18:34:24 +00:00
|
|
|
return 0;
|
2001-08-25 19:33:33 +00:00
|
|
|
}
|
|
|
|
|
2016-03-27 17:08:49 +00:00
|
|
|
int askhk(void *frontend, const char *algname, const char *betteralgs,
|
|
|
|
void (*callback)(void *ctx, int result), void *ctx)
|
|
|
|
{
|
|
|
|
static const char mbtitle[] = "%s Security Alert";
|
|
|
|
static const char msg[] =
|
|
|
|
"The first host key type we have stored for this server\n"
|
|
|
|
"is %s, which is below the configured warning threshold.\n"
|
|
|
|
"The server also provides the following types of host key\n"
|
|
|
|
"above the threshold, which we do not have stored:\n"
|
|
|
|
"%s\n"
|
|
|
|
"Do you want to continue with this connection?\n";
|
|
|
|
char *message, *title;
|
|
|
|
int mbret;
|
|
|
|
|
|
|
|
message = dupprintf(msg, algname, betteralgs);
|
|
|
|
title = dupprintf(mbtitle, appname);
|
|
|
|
mbret = MessageBox(NULL, message, title,
|
|
|
|
MB_ICONWARNING | MB_YESNO | MB_DEFBUTTON2);
|
|
|
|
socket_reselect_all();
|
|
|
|
sfree(message);
|
|
|
|
sfree(title);
|
|
|
|
if (mbret == IDYES)
|
|
|
|
return 1;
|
|
|
|
else
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2001-01-07 18:24:59 +00:00
|
|
|
/*
|
|
|
|
* Ask whether to wipe a session log file before writing to it.
|
|
|
|
* Returns 2 for wipe, 1 for append, 0 for cancel (don't log).
|
|
|
|
*/
|
2011-10-02 11:01:57 +00:00
|
|
|
int askappend(void *frontend, Filename *filename,
|
2005-02-18 18:33:31 +00:00
|
|
|
void (*callback)(void *ctx, int result), void *ctx)
|
2001-05-06 14:35:20 +00:00
|
|
|
{
|
2001-01-07 18:24:59 +00:00
|
|
|
static const char msgtemplate[] =
|
|
|
|
"The session log file \"%.*s\" already exists.\n"
|
|
|
|
"You can overwrite it with a new session log,\n"
|
|
|
|
"append your session log to the end of it,\n"
|
|
|
|
"or disable session logging for this session.\n"
|
|
|
|
"Hit Yes to wipe the file, No to append to it,\n"
|
|
|
|
"or Cancel to disable logging.";
|
2003-04-06 14:11:33 +00:00
|
|
|
char *message;
|
|
|
|
char *mbtitle;
|
2001-01-07 18:24:59 +00:00
|
|
|
int mbret;
|
2003-01-12 13:44:35 +00:00
|
|
|
|
2011-10-02 11:01:57 +00:00
|
|
|
message = dupprintf(msgtemplate, FILENAME_MAX, filename->path);
|
2003-04-06 14:11:33 +00:00
|
|
|
mbtitle = dupprintf("%s Log to File", appname);
|
2001-01-07 18:24:59 +00:00
|
|
|
|
|
|
|
mbret = MessageBox(NULL, message, mbtitle,
|
2005-02-15 19:22:47 +00:00
|
|
|
MB_ICONQUESTION | MB_YESNOCANCEL | MB_DEFBUTTON3);
|
2003-04-06 14:11:33 +00:00
|
|
|
|
2007-01-08 19:38:39 +00:00
|
|
|
socket_reselect_all();
|
|
|
|
|
2003-04-06 14:11:33 +00:00
|
|
|
sfree(message);
|
|
|
|
sfree(mbtitle);
|
|
|
|
|
2001-01-07 18:24:59 +00:00
|
|
|
if (mbret == IDYES)
|
|
|
|
return 2;
|
|
|
|
else if (mbret == IDNO)
|
|
|
|
return 1;
|
|
|
|
else
|
|
|
|
return 0;
|
|
|
|
}
|
2001-11-25 14:31:46 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Warn about the obsolescent key file format.
|
2002-10-26 12:58:13 +00:00
|
|
|
*
|
|
|
|
* Uniquely among these functions, this one does _not_ expect a
|
|
|
|
* frontend handle. This means that if PuTTY is ported to a
|
|
|
|
* platform which requires frontend handles, this function will be
|
|
|
|
* an anomaly. Fortunately, the problem it addresses will not have
|
|
|
|
* been present on that platform, so it can plausibly be
|
|
|
|
* implemented as an empty function.
|
2001-11-25 14:31:46 +00:00
|
|
|
*/
|
|
|
|
void old_keyfile_warning(void)
|
|
|
|
{
|
2003-04-06 14:11:33 +00:00
|
|
|
static const char mbtitle[] = "%s Key File Warning";
|
2001-11-25 14:31:46 +00:00
|
|
|
static const char message[] =
|
2005-03-10 16:36:05 +00:00
|
|
|
"You are loading an SSH-2 private key which has an\n"
|
2001-11-25 14:31:46 +00:00
|
|
|
"old version of the file format. This means your key\n"
|
|
|
|
"file is not fully tamperproof. Future versions of\n"
|
2003-04-06 14:11:33 +00:00
|
|
|
"%s may stop supporting this private key format,\n"
|
2001-11-25 14:31:46 +00:00
|
|
|
"so we recommend you convert your key to the new\n"
|
|
|
|
"format.\n"
|
|
|
|
"\n"
|
|
|
|
"You can perform this conversion by loading the key\n"
|
|
|
|
"into PuTTYgen and then saving it again.";
|
|
|
|
|
2003-04-06 14:11:33 +00:00
|
|
|
char *msg, *title;
|
|
|
|
msg = dupprintf(message, appname);
|
|
|
|
title = dupprintf(mbtitle, appname);
|
|
|
|
|
|
|
|
MessageBox(NULL, msg, title, MB_OK);
|
|
|
|
|
2007-01-08 19:38:39 +00:00
|
|
|
socket_reselect_all();
|
|
|
|
|
2003-04-06 14:11:33 +00:00
|
|
|
sfree(msg);
|
|
|
|
sfree(title);
|
2001-11-25 14:31:46 +00:00
|
|
|
}
|