Support for doing DNS at the proxy end. I've invented a new type of
[u/mdw/putty] / windlg.c
index 7ee5c97..a8603e6 100644 (file)
--- a/windlg.c
+++ b/windlg.c
@@ -27,6 +27,10 @@ static int requested_help;
 
 static struct prefslist cipherlist;
 
+struct sesslist sesslist;             /* exported to window.c */
+
+#define PRINTER_DISABLED_STRING "None (printing disabled)"
+
 void force_normal(HWND hwnd)
 {
     static int recurse = 0;
@@ -138,7 +142,7 @@ static int CALLBACK LogProc(HWND hwnd, UINT msg,
                            memcpy(p, sel_nl, sizeof(sel_nl));
                            p += sizeof(sel_nl);
                        }
-                       write_aclip(clipdata, size, TRUE);
+                       write_aclip(NULL, clipdata, size, TRUE);
                        sfree(clipdata);
                    }
                    sfree(selitems);
@@ -296,8 +300,6 @@ enum { IDCX_ABOUT =
     IDC_KPNORMAL,
     IDC_KPAPPLIC,
     IDC_KPNH,
-    IDC_NOAPPLICK,
-    IDC_NOAPPLICC,
     IDC_CURSTATIC,
     IDC_CURNORMAL,
     IDC_CURAPPLIC,
@@ -309,6 +311,7 @@ enum { IDCX_ABOUT =
     IDC_TITLE_TERMINAL,
     IDC_BOX_TERMINAL1,
     IDC_BOX_TERMINAL2,
+    IDC_BOX_TERMINAL3,
     IDC_WRAPMODE,
     IDC_DECOM,
     IDC_LFHASCR,
@@ -324,8 +327,23 @@ enum { IDCX_ABOUT =
     IDC_EDITBACKEND,
     IDC_EDITYES,
     IDC_EDITNO,
+    IDC_PRINTERSTATIC,
+    IDC_PRINTER,
     terminalpanelend,
 
+    featurespanelstart,
+    IDC_TITLE_FEATURES,
+    IDC_BOX_FEATURES1,
+    IDC_NOAPPLICK,
+    IDC_NOAPPLICC,
+    IDC_NOMOUSEREP,
+    IDC_NORESIZE,
+    IDC_NOALTSCREEN,
+    IDC_NOWINTITLE,
+    IDC_NODBACKSPACE,
+    IDC_NOCHARSET,
+    featurespanelend,
+
     bellpanelstart,
     IDC_TITLE_BELL,
     IDC_BOX_BELL1,
@@ -422,6 +440,37 @@ enum { IDCX_ABOUT =
     IDC_NODELAY,
     connectionpanelend,
 
+    proxypanelstart,
+    IDC_TITLE_PROXY,
+    IDC_BOX_PROXY1,
+    IDC_PROXYTYPESTATIC,
+    IDC_PROXYTYPENONE,
+    IDC_PROXYTYPEHTTP,
+    IDC_PROXYTYPESOCKS,
+    IDC_PROXYTYPETELNET,
+    IDC_PROXYHOSTSTATIC,
+    IDC_PROXYHOSTEDIT,
+    IDC_PROXYPORTSTATIC,
+    IDC_PROXYPORTEDIT,
+    IDC_PROXYEXCLUDESTATIC,
+    IDC_PROXYEXCLUDEEDIT,
+    IDC_PROXYLOCALHOST,
+    IDC_PROXYDNSSTATIC,
+    IDC_PROXYDNSNO,
+    IDC_PROXYDNSAUTO,
+    IDC_PROXYDNSYES,
+    IDC_PROXYUSERSTATIC,
+    IDC_PROXYUSEREDIT,
+    IDC_PROXYPASSSTATIC,
+    IDC_PROXYPASSEDIT,
+    IDC_BOX_PROXY2,
+    IDC_PROXYTELNETCMDSTATIC,
+    IDC_PROXYTELNETCMDEDIT,
+    IDC_PROXYSOCKSVERSTATIC,
+    IDC_PROXYSOCKSVER5,
+    IDC_PROXYSOCKSVER4,
+    proxypanelend,
+
     telnetpanelstart,
     IDC_TITLE_TELNET,
     IDC_BOX_TELNET1,
@@ -467,11 +516,12 @@ enum { IDCX_ABOUT =
     IDC_CIPHERLIST,
     IDC_CIPHERUP,
     IDC_CIPHERDN,
-    IDC_BUGGYMAC,
     IDC_SSH2DES,
     IDC_SSHPROTSTATIC,
+    IDC_SSHPROT1ONLY,
     IDC_SSHPROT1,
     IDC_SSHPROT2,
+    IDC_SSHPROT2ONLY,
     IDC_CMDSTATIC,
     IDC_CMDEDIT,
     IDC_COMPRESS,
@@ -490,6 +540,25 @@ enum { IDCX_ABOUT =
     IDC_AUTHKI,
     sshauthpanelend,
 
+    sshbugspanelstart,
+    IDC_TITLE_SSHBUGS,
+    IDC_BOX_SSHBUGS1,
+    IDC_BUGS_IGNORE1,
+    IDC_BUGD_IGNORE1,
+    IDC_BUGS_PLAINPW1,
+    IDC_BUGD_PLAINPW1,
+    IDC_BUGS_RSA1,
+    IDC_BUGD_RSA1,
+    IDC_BUGS_HMAC2,
+    IDC_BUGD_HMAC2,
+    IDC_BUGS_DERIVEKEY2,
+    IDC_BUGD_DERIVEKEY2,
+    IDC_BUGS_RSAPAD2,
+    IDC_BUGD_RSAPAD2,
+    IDC_BUGS_DHGEX2,
+    IDC_BUGD_DHGEX2,
+    sshbugspanelend,
+
     selectionpanelstart,
     IDC_TITLE_SELECTION,
     IDC_BOX_SELECTION1,
@@ -662,9 +731,7 @@ char *help_context_cmd(int id)
       case IDC_KPSTATIC:
       case IDC_KPNORMAL:
       case IDC_KPAPPLIC:
-      case IDC_NOAPPLICK:
         return "JI(`',`keyboard.appkeypad')";
-      case IDC_NOAPPLICC:
       case IDC_CURSTATIC:
       case IDC_CURNORMAL:
       case IDC_CURAPPLIC:
@@ -676,6 +743,22 @@ char *help_context_cmd(int id)
       case IDC_CTRLALTKEYS:
         return "JI(`',`keyboard.ctrlalt')";
 
+      case IDC_NOAPPLICK:
+      case IDC_NOAPPLICC:
+        return "JI(`',`features.application')";
+      case IDC_NOMOUSEREP:
+        return "JI(`',`features.mouse')";
+      case IDC_NORESIZE:
+        return "JI(`',`features.resize')";
+      case IDC_NOALTSCREEN:
+        return "JI(`',`features.altscreen')";
+      case IDC_NOWINTITLE:
+        return "JI(`',`features.retitle')";
+      case IDC_NODBACKSPACE:
+        return "JI(`',`features.dbackspace')";
+      case IDC_NOCHARSET:
+        return "JI(`',`features.charset')";
+
       case IDC_WRAPMODE:
         return "JI(`',`terminal.autowrap')";
       case IDC_DECOM:
@@ -699,6 +782,9 @@ char *help_context_cmd(int id)
       case IDC_EDITYES:
       case IDC_EDITNO:
         return "JI(`',`terminal.localedit')";
+      case IDC_PRINTERSTATIC:
+      case IDC_PRINTER:
+       return "JI(`',`terminal.printing')";
 
       case IDC_BELLSTATIC:
       case IDC_BELL_DISABLED:
@@ -788,6 +874,39 @@ char *help_context_cmd(int id)
       case IDC_NODELAY:
         return "JI(`',`connection.nodelay')";
 
+      case IDC_PROXYTYPESTATIC:
+      case IDC_PROXYTYPENONE:
+      case IDC_PROXYTYPEHTTP:
+      case IDC_PROXYTYPESOCKS:
+      case IDC_PROXYTYPETELNET:
+        return "JI(`',`proxy.type')";
+      case IDC_PROXYHOSTSTATIC:
+      case IDC_PROXYHOSTEDIT:
+      case IDC_PROXYPORTSTATIC:
+      case IDC_PROXYPORTEDIT:
+        return "JI(`',`proxy.main')";
+      case IDC_PROXYEXCLUDESTATIC:
+      case IDC_PROXYEXCLUDEEDIT:
+      case IDC_PROXYLOCALHOST:
+        return "JI(`',`proxy.exclude')";
+      case IDC_PROXYDNSSTATIC:
+      case IDC_PROXYDNSNO:
+      case IDC_PROXYDNSAUTO:
+      case IDC_PROXYDNSYES:
+       return "JI(`',`proxy.dns')";
+      case IDC_PROXYUSERSTATIC:
+      case IDC_PROXYUSEREDIT:
+      case IDC_PROXYPASSSTATIC:
+      case IDC_PROXYPASSEDIT:
+        return "JI(`',`proxy.auth')";
+      case IDC_PROXYTELNETCMDSTATIC:
+      case IDC_PROXYTELNETCMDEDIT:
+        return "JI(`',`proxy.command')";
+      case IDC_PROXYSOCKSVERSTATIC:
+      case IDC_PROXYSOCKSVER5:
+      case IDC_PROXYSOCKSVER4:
+        return "JI(`',`proxy.socksver')";
+
       case IDC_TSSTATIC:
       case IDC_TSEDIT:
         return "JI(`',`telnet.termspeed')";
@@ -828,11 +947,11 @@ char *help_context_cmd(int id)
       case IDC_CIPHERDN:
       case IDC_SSH2DES:
         return "JI(`',`ssh.ciphers')";
-      case IDC_BUGGYMAC:
-        return "JI(`',`ssh.buggymac')";
       case IDC_SSHPROTSTATIC:
+      case IDC_SSHPROT1ONLY:
       case IDC_SSHPROT1:
       case IDC_SSHPROT2:
+      case IDC_SSHPROT2ONLY:
         return "JI(`',`ssh.protocol')";
       case IDC_CMDSTATIC:
       case IDC_CMDEDIT:
@@ -922,6 +1041,28 @@ char *help_context_cmd(int id)
       case IDC_RPORT_ALL:
         return "JI(`',`ssh.tunnels.portfwd.localhost')";
 
+      case IDC_BUGS_IGNORE1:
+      case IDC_BUGD_IGNORE1:
+       return "JI(`',`ssh.bugs.ignore1')";
+      case IDC_BUGS_PLAINPW1:
+      case IDC_BUGD_PLAINPW1:
+       return "JI(`',`ssh.bugs.plainpw1')";
+      case IDC_BUGS_RSA1:
+      case IDC_BUGD_RSA1:
+       return "JI(`',`ssh.bugs.rsa1')";
+      case IDC_BUGS_HMAC2:
+      case IDC_BUGD_HMAC2:
+       return "JI(`',`ssh.bugs.hmac2')";
+      case IDC_BUGS_DERIVEKEY2:
+      case IDC_BUGD_DERIVEKEY2:
+       return "JI(`',`ssh.bugs.derivekey2')";
+      case IDC_BUGS_RSAPAD2:
+      case IDC_BUGD_RSAPAD2:
+       return "JI(`',`ssh.bugs.rsapad2')";
+      case IDC_BUGS_DHGEX2:
+      case IDC_BUGD_DHGEX2:
+       return "JI(`',`ssh.bugs.dhgex2')";
+
       default:
         return NULL;
     }
@@ -941,9 +1082,9 @@ static void init_dlg_ctrls(HWND hwnd, int keepsess)
        n = SendDlgItemMessage(hwnd, IDC_SESSLIST, LB_GETCOUNT, 0, 0);
        for (i = n; i-- > 0;)
            SendDlgItemMessage(hwnd, IDC_SESSLIST, LB_DELETESTRING, i, 0);
-       for (i = 0; i < nsessions; i++)
+       for (i = 0; i < sesslist.nsessions; i++)
            SendDlgItemMessage(hwnd, IDC_SESSLIST, LB_ADDSTRING,
-                              0, (LPARAM) (sessions[i]));
+                              0, (LPARAM) (sesslist.sessions[i]));
     }
     SetDlgItemInt(hwnd, IDC_PORT, cfg.port, FALSE);
     CheckRadioButton(hwnd, IDC_PROTRAW, IDC_PROTSSH,
@@ -967,6 +1108,12 @@ static void init_dlg_ctrls(HWND hwnd, int keepsess)
                     cfg.funky_type == 5 ? IDC_FUNCSCO : IDC_FUNCTILDE);
     CheckDlgButton(hwnd, IDC_NOAPPLICC, cfg.no_applic_c);
     CheckDlgButton(hwnd, IDC_NOAPPLICK, cfg.no_applic_k);
+    CheckDlgButton(hwnd, IDC_NOMOUSEREP, cfg.no_mouse_rep);
+    CheckDlgButton(hwnd, IDC_NORESIZE, cfg.no_remote_resize);
+    CheckDlgButton(hwnd, IDC_NOALTSCREEN, cfg.no_alt_screen);
+    CheckDlgButton(hwnd, IDC_NOWINTITLE, cfg.no_remote_wintitle);
+    CheckDlgButton(hwnd, IDC_NODBACKSPACE, cfg.no_dbackspace);
+    CheckDlgButton(hwnd, IDC_NOCHARSET, cfg.no_remote_charset);
     CheckRadioButton(hwnd, IDC_CURNORMAL, IDC_CURAPPLIC,
                     cfg.app_cursor ? IDC_CURAPPLIC : IDC_CURNORMAL);
     CheckRadioButton(hwnd, IDC_KPNORMAL, IDC_KPNH,
@@ -1080,12 +1227,13 @@ static void init_dlg_ctrls(HWND hwnd, int keepsess)
     SetDlgItemText(hwnd, IDC_LOGEDIT, cfg.username);
     CheckDlgButton(hwnd, IDC_NOPTY, cfg.nopty);
     CheckDlgButton(hwnd, IDC_COMPRESS, cfg.compression);
-    CheckDlgButton(hwnd, IDC_BUGGYMAC, cfg.buggymac);
     CheckDlgButton(hwnd, IDC_SSH2DES, cfg.ssh2_des_cbc);
     CheckDlgButton(hwnd, IDC_AGENTFWD, cfg.agentfwd);
     CheckDlgButton(hwnd, IDC_CHANGEUSER, cfg.change_username);
-    CheckRadioButton(hwnd, IDC_SSHPROT1, IDC_SSHPROT2,
-                    cfg.sshprot == 1 ? IDC_SSHPROT1 : IDC_SSHPROT2);
+    CheckRadioButton(hwnd, IDC_SSHPROT1ONLY, IDC_SSHPROT2ONLY,
+                    cfg.sshprot == 1 ? IDC_SSHPROT1 :
+                    cfg.sshprot == 2 ? IDC_SSHPROT2 :
+                    cfg.sshprot == 3 ? IDC_SSHPROT2ONLY : IDC_SSHPROT1ONLY);
     CheckDlgButton(hwnd, IDC_AUTHTIS, cfg.try_tis_auth);
     CheckDlgButton(hwnd, IDC_AUTHKI, cfg.try_ki_auth);
     SetDlgItemText(hwnd, IDC_PKEDIT, cfg.keyfile);
@@ -1172,7 +1320,24 @@ static void init_dlg_ctrls(HWND hwnd, int keepsess)
        }
        SetDlgItemText(hwnd, IDC_CODEPAGE, cfg.line_codepage);
     }
-    
+
+    {
+       int i, nprinters;
+       printer_enum *pe;
+       pe = printer_start_enum(&nprinters);
+       SendDlgItemMessage(hwnd, IDC_PRINTER, CB_RESETCONTENT, 0, 0);
+       SendDlgItemMessage(hwnd, IDC_PRINTER, CB_ADDSTRING,
+                          0, (LPARAM) PRINTER_DISABLED_STRING);
+       for (i = 0; i < nprinters; i++) {
+           char *printer_name = printer_get_name(pe, i);
+           SendDlgItemMessage(hwnd, IDC_PRINTER, CB_ADDSTRING,
+                              0, (LPARAM) printer_name);
+       }
+       printer_finish_enum(pe);
+       SetDlgItemText(hwnd, IDC_PRINTER,
+                      *cfg.printer ? cfg.printer : PRINTER_DISABLED_STRING);
+    }
+
     CheckRadioButton(hwnd, IDC_VTXWINDOWS, IDC_VTUNICODE,
                     cfg.vtmode == VT_XWINDOWS ? IDC_VTXWINDOWS :
                     cfg.vtmode == VT_OEMANSI ? IDC_VTOEMANSI :
@@ -1186,6 +1351,76 @@ static void init_dlg_ctrls(HWND hwnd, int keepsess)
     CheckDlgButton(hwnd, IDC_LPORT_ALL, cfg.lport_acceptall);
     CheckDlgButton(hwnd, IDC_RPORT_ALL, cfg.rport_acceptall);
     CheckRadioButton(hwnd, IDC_PFWDLOCAL, IDC_PFWDREMOTE, IDC_PFWDLOCAL);
+
+    /* proxy config */
+    CheckRadioButton(hwnd, IDC_PROXYTYPENONE, IDC_PROXYTYPETELNET,
+                    cfg.proxy_type == PROXY_HTTP ? IDC_PROXYTYPEHTTP :
+                    cfg.proxy_type == PROXY_SOCKS ? IDC_PROXYTYPESOCKS :
+                    cfg.proxy_type == PROXY_TELNET ? IDC_PROXYTYPETELNET : IDC_PROXYTYPENONE);
+    SetDlgItemText(hwnd, IDC_PROXYHOSTEDIT, cfg.proxy_host);
+    SetDlgItemInt(hwnd, IDC_PROXYPORTEDIT, cfg.proxy_port, FALSE);
+    SetDlgItemText(hwnd, IDC_PROXYEXCLUDEEDIT, cfg.proxy_exclude_list);
+    CheckDlgButton(hwnd, IDC_PROXYLOCALHOST, cfg.even_proxy_localhost);
+    CheckRadioButton(hwnd, IDC_PROXYDNSNO, IDC_PROXYDNSYES,
+                    cfg.proxy_dns == PROXYDNS_NO ? IDC_PROXYDNSNO :
+                    cfg.proxy_dns == PROXYDNS_YES ? IDC_PROXYDNSYES :
+                    IDC_PROXYDNSAUTO);
+    SetDlgItemText(hwnd, IDC_PROXYTELNETCMDEDIT, cfg.proxy_telnet_command);
+    SetDlgItemText(hwnd, IDC_PROXYUSEREDIT, cfg.proxy_username);
+    SetDlgItemText(hwnd, IDC_PROXYPASSEDIT, cfg.proxy_password);
+    CheckRadioButton(hwnd, IDC_PROXYSOCKSVER5, IDC_PROXYSOCKSVER4,
+                    cfg.proxy_socks_version == 4 ? IDC_PROXYSOCKSVER4 : IDC_PROXYSOCKSVER5);
+
+    /* SSH bugs config */
+    SendDlgItemMessage(hwnd, IDC_BUGD_IGNORE1, CB_RESETCONTENT, 0, 0);
+    SendDlgItemMessage(hwnd, IDC_BUGD_IGNORE1, CB_ADDSTRING, 0, (LPARAM)"Auto");
+    SendDlgItemMessage(hwnd, IDC_BUGD_IGNORE1, CB_ADDSTRING, 0, (LPARAM)"Off");
+    SendDlgItemMessage(hwnd, IDC_BUGD_IGNORE1, CB_ADDSTRING, 0, (LPARAM)"On");
+    SendDlgItemMessage(hwnd, IDC_BUGD_IGNORE1, CB_SETCURSEL,
+                      cfg.sshbug_ignore1 == BUG_ON ? 2 :
+                      cfg.sshbug_ignore1 == BUG_OFF ? 1 : 0, 0);
+    SendDlgItemMessage(hwnd, IDC_BUGD_PLAINPW1, CB_RESETCONTENT, 0, 0);
+    SendDlgItemMessage(hwnd, IDC_BUGD_PLAINPW1, CB_ADDSTRING, 0, (LPARAM)"Auto");
+    SendDlgItemMessage(hwnd, IDC_BUGD_PLAINPW1, CB_ADDSTRING, 0, (LPARAM)"Off");
+    SendDlgItemMessage(hwnd, IDC_BUGD_PLAINPW1, CB_ADDSTRING, 0, (LPARAM)"On");
+    SendDlgItemMessage(hwnd, IDC_BUGD_PLAINPW1, CB_SETCURSEL,
+                      cfg.sshbug_plainpw1 == BUG_ON ? 2 :
+                      cfg.sshbug_plainpw1 == BUG_OFF ? 1 : 0, 0);
+    SendDlgItemMessage(hwnd, IDC_BUGD_RSA1, CB_RESETCONTENT, 0, 0);
+    SendDlgItemMessage(hwnd, IDC_BUGD_RSA1, CB_ADDSTRING, 0, (LPARAM)"Auto");
+    SendDlgItemMessage(hwnd, IDC_BUGD_RSA1, CB_ADDSTRING, 0, (LPARAM)"Off");
+    SendDlgItemMessage(hwnd, IDC_BUGD_RSA1, CB_ADDSTRING, 0, (LPARAM)"On");
+    SendDlgItemMessage(hwnd, IDC_BUGD_RSA1, CB_SETCURSEL,
+                      cfg.sshbug_rsa1 == BUG_ON ? 2 :
+                      cfg.sshbug_rsa1 == BUG_OFF ? 1 : 0, 0);
+    SendDlgItemMessage(hwnd, IDC_BUGD_HMAC2, CB_RESETCONTENT, 0, 0);
+    SendDlgItemMessage(hwnd, IDC_BUGD_HMAC2, CB_ADDSTRING, 0, (LPARAM)"Auto");
+    SendDlgItemMessage(hwnd, IDC_BUGD_HMAC2, CB_ADDSTRING, 0, (LPARAM)"Off");
+    SendDlgItemMessage(hwnd, IDC_BUGD_HMAC2, CB_ADDSTRING, 0, (LPARAM)"On");
+    SendDlgItemMessage(hwnd, IDC_BUGD_HMAC2, CB_SETCURSEL,
+                      cfg.sshbug_hmac2 == BUG_ON ? 2 :
+                      cfg.sshbug_hmac2 == BUG_OFF ? 1 : 0, 0);
+    SendDlgItemMessage(hwnd, IDC_BUGD_DERIVEKEY2, CB_RESETCONTENT, 0, 0);
+    SendDlgItemMessage(hwnd, IDC_BUGD_DERIVEKEY2, CB_ADDSTRING, 0, (LPARAM)"Auto");
+    SendDlgItemMessage(hwnd, IDC_BUGD_DERIVEKEY2, CB_ADDSTRING, 0, (LPARAM)"Off");
+    SendDlgItemMessage(hwnd, IDC_BUGD_DERIVEKEY2, CB_ADDSTRING, 0, (LPARAM)"On");
+    SendDlgItemMessage(hwnd, IDC_BUGD_DERIVEKEY2, CB_SETCURSEL,
+                      cfg.sshbug_derivekey2 == BUG_ON ? 2 :
+                      cfg.sshbug_derivekey2 == BUG_OFF ? 1 : 0, 0);
+    SendDlgItemMessage(hwnd, IDC_BUGD_RSAPAD2, CB_RESETCONTENT, 0, 0);
+    SendDlgItemMessage(hwnd, IDC_BUGD_RSAPAD2, CB_ADDSTRING, 0, (LPARAM)"Auto");
+    SendDlgItemMessage(hwnd, IDC_BUGD_RSAPAD2, CB_ADDSTRING, 0, (LPARAM)"Off");
+    SendDlgItemMessage(hwnd, IDC_BUGD_RSAPAD2, CB_ADDSTRING, 0, (LPARAM)"On");
+    SendDlgItemMessage(hwnd, IDC_BUGD_RSAPAD2, CB_SETCURSEL,
+                      cfg.sshbug_rsapad2 == BUG_ON ? 2 :
+                      cfg.sshbug_rsapad2 == BUG_OFF ? 1 : 0, 0);
+    SendDlgItemMessage(hwnd, IDC_BUGD_DHGEX2, CB_RESETCONTENT, 0, 0);
+    SendDlgItemMessage(hwnd, IDC_BUGD_DHGEX2, CB_ADDSTRING, 0, (LPARAM)"Auto");
+    SendDlgItemMessage(hwnd, IDC_BUGD_DHGEX2, CB_ADDSTRING, 0, (LPARAM)"Off");
+    SendDlgItemMessage(hwnd, IDC_BUGD_DHGEX2, CB_ADDSTRING, 0, (LPARAM)"On");
+    SendDlgItemMessage(hwnd, IDC_BUGD_DHGEX2, CB_SETCURSEL,
+                      cfg.sshbug_dhgex2 == BUG_ON ? 2 :
+                      cfg.sshbug_dhgex2 == BUG_OFF ? 1 : 0, 0);
 }
 
 struct treeview_faff {
@@ -1299,7 +1534,7 @@ static void create_controls(HWND hwnd, int dlgtype, int panel)
     }
 
     if (panel == terminalpanelstart) {
-       /* The Terminal panel. Accelerators used: [acgoh] wdren lts */
+       /* The Terminal panel. Accelerators used: [acgoh] wdren lts */
        struct ctlpos cp;
        ctlposinit(&cp, hwnd, 80, 3, 13);
        bartitle(&cp, "Options controlling the terminal emulation",
@@ -1323,6 +1558,34 @@ static void create_controls(HWND hwnd, int dlgtype, int panel)
                  "Auto", IDC_EDITBACKEND,
                  "Force on", IDC_EDITYES, "Force off", IDC_EDITNO, NULL);
        endbox(&cp);
+
+       beginbox(&cp, "Remote-controlled printing", IDC_BOX_TERMINAL3);
+       combobox(&cp, "&Printer to send ANSI printer output to:",
+                IDC_PRINTERSTATIC, IDC_PRINTER);
+       endbox(&cp);
+    }
+
+    if (panel == featurespanelstart) {
+       /* The Features panel. Accelerators used: [acgoh] ukswtbrx */
+       struct ctlpos cp;
+       ctlposinit(&cp, hwnd, 80, 3, 13);
+       bartitle(&cp, "Enabling and disabling advanced terminal features ",
+                IDC_TITLE_FEATURES);
+       beginbox(&cp, NULL, IDC_BOX_FEATURES1);
+       checkbox(&cp, "Disable application c&ursor keys mode", IDC_NOAPPLICC);
+       checkbox(&cp, "Disable application &keypad mode", IDC_NOAPPLICK);
+       checkbox(&cp, "Disable &xterm-style mouse reporting", IDC_NOMOUSEREP);
+       checkbox(&cp, "Disable remote-controlled terminal re&sizing",
+                IDC_NORESIZE);
+       checkbox(&cp, "Disable s&witching to alternate terminal screen",
+                IDC_NOALTSCREEN);
+       checkbox(&cp, "Disable remote-controlled window &title changing",
+                IDC_NOWINTITLE);
+       checkbox(&cp, "Disable destructive &backspace on server sending ^?",
+                IDC_NODBACKSPACE);
+       checkbox(&cp, "Disable remote-controlled cha&racter set configuration",
+                IDC_NOCHARSET);
+       endbox(&cp);
     }
 
     if (panel == bellpanelstart) {
@@ -1363,7 +1626,7 @@ static void create_controls(HWND hwnd, int dlgtype, int panel)
     }
 
     if (panel == keyboardpanelstart) {
-       /* The Keyboard panel. Accelerators used: [acgoh] bef ruyntd */
+       /* The Keyboard panel. Accelerators used: [acgoh] bef rntd */
        struct ctlpos cp;
        ctlposinit(&cp, hwnd, 80, 3, 13);
        bartitle(&cp, "Options controlling the effects of keys",
@@ -1382,15 +1645,9 @@ static void create_controls(HWND hwnd, int dlgtype, int panel)
                  "VT100+", IDC_FUNCVT100P, "SCO", IDC_FUNCSCO, NULL);
        endbox(&cp);
        beginbox(&cp, "Application keypad settings:", IDC_BOX_KEYBOARD2);
-       checkbox(&cp,
-                "Application c&ursor keys totally disabled",
-                IDC_NOAPPLICC);
        radioline(&cp, "Initial state of cu&rsor keys:", IDC_CURSTATIC, 2,
                  "Normal", IDC_CURNORMAL,
                  "Application", IDC_CURAPPLIC, NULL);
-       checkbox(&cp,
-                "Application ke&ypad keys totally disabled",
-                IDC_NOAPPLICK);
        radioline(&cp, "Initial state of &numeric keypad:", IDC_KPSTATIC,
                  3, "Normal", IDC_KPNORMAL, "Application", IDC_KPAPPLIC,
                  "NetHack", IDC_KPNH, NULL);
@@ -1608,6 +1865,48 @@ static void create_controls(HWND hwnd, int dlgtype, int panel)
        }
     }
 
+    if (panel == proxypanelstart) {
+       /* The Proxy panel. Accelerators used: [acgoh] ntslypeuwmvxd */
+       struct ctlpos cp;
+       ctlposinit(&cp, hwnd, 80, 3, 13);
+       if (dlgtype == 0) {
+           bartitle(&cp, "Options controlling proxy usage",
+                    IDC_TITLE_PROXY);
+           beginbox(&cp, "Proxy basics", IDC_BOX_PROXY1);
+           radioline(&cp, "Proxy type:", IDC_PROXYTYPESTATIC, 4,
+                     "&None", IDC_PROXYTYPENONE,
+                     "H&TTP", IDC_PROXYTYPEHTTP,
+                     "&SOCKS", IDC_PROXYTYPESOCKS,
+                     "Te&lnet", IDC_PROXYTYPETELNET, NULL);
+           multiedit(&cp,
+                     "Prox&y Host", IDC_PROXYHOSTSTATIC, IDC_PROXYHOSTEDIT, 80,
+                     "&Port", IDC_PROXYPORTSTATIC, IDC_PROXYPORTEDIT, 20, NULL);
+           multiedit(&cp,
+                     "&Exclude Hosts/IPs", IDC_PROXYEXCLUDESTATIC,
+                     IDC_PROXYEXCLUDEEDIT, 100, NULL);
+           checkbox(&cp, "Consider pro&xying local host connections",
+                    IDC_PROXYLOCALHOST);
+           radioline(&cp, "Do &DNS name lookup at proxy end:",
+                     IDC_PROXYDNSSTATIC, 3,
+                     "No", IDC_PROXYDNSNO,
+                     "Auto", IDC_PROXYDNSAUTO,
+                     "Yes", IDC_PROXYDNSYES, NULL);
+           staticedit(&cp, "&Username", IDC_PROXYUSERSTATIC,
+                      IDC_PROXYUSEREDIT, 60);
+           staticpassedit(&cp, "Pass&word", IDC_PROXYPASSSTATIC,
+                          IDC_PROXYPASSEDIT, 60);
+           endbox(&cp);
+           beginbox(&cp, "Misc. proxy settings", IDC_BOX_PROXY2);
+           multiedit(&cp,
+                     "Telnet co&mmand", IDC_PROXYTELNETCMDSTATIC,
+                     IDC_PROXYTELNETCMDEDIT, 100, NULL);
+           radioline(&cp, "SOCKS &Version", IDC_PROXYSOCKSVERSTATIC,
+                     2, "Version 5", IDC_PROXYSOCKSVER5, "Version 4",
+                     IDC_PROXYSOCKSVER4, NULL);
+           endbox(&cp);
+       }
+    }
+
     if (panel == telnetpanelstart) {
        /* The Telnet panel. Accelerators used: [acgoh] svldr bftk */
        struct ctlpos cp;
@@ -1655,7 +1954,7 @@ static void create_controls(HWND hwnd, int dlgtype, int panel)
     }
 
     if (panel == sshpanelstart) {
-       /* The SSH panel. Accelerators used: [acgoh] r pe12i sd */
+       /* The SSH panel. Accelerators used: [acgoh] r pe12ni sd */
        struct ctlpos cp;
        ctlposinit(&cp, hwnd, 80, 3, 13);
        if (dlgtype == 0) {
@@ -1670,10 +1969,10 @@ static void create_controls(HWND hwnd, int dlgtype, int panel)
            checkbox(&cp, "Don't allocate a &pseudo-terminal", IDC_NOPTY);
            checkbox(&cp, "Enable compr&ession", IDC_COMPRESS);
            radioline(&cp, "Preferred SSH protocol version:",
-                     IDC_SSHPROTSTATIC, 2,
-                     "&1", IDC_SSHPROT1, "&2", IDC_SSHPROT2, NULL);
-           checkbox(&cp, "&Imitate SSH 2 MAC bug in commercial <= v2.3.x",
-                    IDC_BUGGYMAC);
+                     IDC_SSHPROTSTATIC, 4,
+                     "1 on&ly", IDC_SSHPROT1ONLY,
+                     "&1", IDC_SSHPROT1, "&2", IDC_SSHPROT2,
+                     "2 o&nly", IDC_SSHPROT2ONLY, NULL);
            endbox(&cp);
            beginbox(&cp, "Encryption options", IDC_BOX_SSH3);
            prefslist(&cipherlist, &cp, "Encryption cipher &selection policy:",
@@ -1711,6 +2010,33 @@ static void create_controls(HWND hwnd, int dlgtype, int panel)
        }
     }
 
+    if (panel == sshbugspanelstart) {
+       /* The SSH bugs panel. Accelerators used: [acgoh] isrmep */
+       struct ctlpos cp;
+       ctlposinit(&cp, hwnd, 80, 3, 13);
+       if (dlgtype == 0) {
+           bartitle(&cp, "Workarounds for SSH server bugs",
+                    IDC_TITLE_SSHBUGS);
+           beginbox(&cp, "Detection of known bugs in SSH servers",
+                    IDC_BOX_SSHBUGS1);
+           staticddl(&cp, "Chokes on SSH1 &ignore messages",
+                     IDC_BUGS_IGNORE1, IDC_BUGD_IGNORE1, 20);
+           staticddl(&cp, "Refuses all SSH1 pa&ssword camouflage",
+                     IDC_BUGS_PLAINPW1, IDC_BUGD_PLAINPW1, 20);
+           staticddl(&cp, "Chokes on SSH1 &RSA authentication",
+                     IDC_BUGS_RSA1, IDC_BUGD_RSA1, 20);
+           staticddl(&cp, "Miscomputes SSH2 H&MAC keys",
+                     IDC_BUGS_HMAC2, IDC_BUGD_HMAC2, 20);
+           staticddl(&cp, "Miscomputes SSH2 &encryption keys",
+                     IDC_BUGS_DERIVEKEY2, IDC_BUGD_DERIVEKEY2, 20);
+           staticddl(&cp, "Requires &padding on SSH2 RSA signatures",
+                     IDC_BUGS_RSAPAD2, IDC_BUGD_RSAPAD2, 20);
+           staticddl(&cp, "Chokes on &Diffie-Hellman group exchange",
+                     IDC_BUGS_DHGEX2, IDC_BUGD_DHGEX2, 20);
+           endbox(&cp);
+       }
+    }
+
     if (panel == tunnelspanelstart) {
        /* The Tunnels panel. Accelerators used: [acgoh] deilmrstxp */
        struct ctlpos cp;
@@ -1734,10 +2060,9 @@ static void create_controls(HWND hwnd, int dlgtype, int panel)
                      "Add new forwarded port:", IDC_PFWDSTATIC2,
                      "&Source port", IDC_SPORTSTATIC, IDC_SPORTEDIT,
                      "Dest&ination", IDC_DPORTSTATIC, IDC_DPORTEDIT,
-                     "A&dd", IDC_PFWDADD);
-           bareradioline(&cp, 2,
-                         "&Local", IDC_PFWDLOCAL,
-                         "Re&mote", IDC_PFWDREMOTE, NULL);
+                     "A&dd", IDC_PFWDADD,
+                     "&Local", IDC_PFWDLOCAL,
+                     "Re&mote", IDC_PFWDREMOTE);
            endbox(&cp);
 
        }
@@ -1758,11 +2083,11 @@ static int load_selected_session(HWND hwnd)
        MessageBeep(0);
        return 0;
     }
-    isdef = !strcmp(sessions[n], "Default Settings");
-    load_settings(sessions[n], !isdef, &cfg);
+    isdef = !strcmp(sesslist.sessions[n], "Default Settings");
+    load_settings(sesslist.sessions[n], !isdef, &cfg);
     init_dlg_ctrls(hwnd, TRUE);
     if (!isdef)
-       SetDlgItemText(hwnd, IDC_SESSEDIT, sessions[n]);
+       SetDlgItemText(hwnd, IDC_SESSEDIT, sesslist.sessions[n]);
     else
        SetDlgItemText(hwnd, IDC_SESSEDIT, "");
     /* Restore the selection, which will have been clobbered by
@@ -1869,6 +2194,7 @@ static int GenericMainDlgProc(HWND hwnd, UINT msg,
        treeview_insert(&tvfaff, 0, "Terminal");
        treeview_insert(&tvfaff, 1, "Keyboard");
        treeview_insert(&tvfaff, 1, "Bell");
+       treeview_insert(&tvfaff, 1, "Features");
        treeview_insert(&tvfaff, 0, "Window");
        treeview_insert(&tvfaff, 1, "Appearance");
        treeview_insert(&tvfaff, 1, "Behaviour");
@@ -1877,6 +2203,7 @@ static int GenericMainDlgProc(HWND hwnd, UINT msg,
        treeview_insert(&tvfaff, 1, "Colours");
        treeview_insert(&tvfaff, 0, "Connection");
        if (dlgtype == 0) {
+           treeview_insert(&tvfaff, 1, "Proxy");
            treeview_insert(&tvfaff, 1, "Telnet");
            treeview_insert(&tvfaff, 1, "Rlogin");
            if (backends[3].backend != NULL) {
@@ -1885,6 +2212,7 @@ static int GenericMainDlgProc(HWND hwnd, UINT msg,
                /* XXX make it closed by default? */
                treeview_insert(&tvfaff, 2, "Auth");
                treeview_insert(&tvfaff, 2, "Tunnels");
+               treeview_insert(&tvfaff, 2, "Bugs");
            }
        }
 
@@ -1948,6 +2276,8 @@ static int GenericMainDlgProc(HWND hwnd, UINT msg,
                create_controls(hwnd, dlgtype, terminalpanelstart);
            if (!strcmp(buffer, "Bell"))
                create_controls(hwnd, dlgtype, bellpanelstart);
+           if (!strcmp(buffer, "Features"))
+               create_controls(hwnd, dlgtype, featurespanelstart);
            if (!strcmp(buffer, "Window"))
                create_controls(hwnd, dlgtype, windowpanelstart);
            if (!strcmp(buffer, "Appearance"))
@@ -1958,6 +2288,8 @@ static int GenericMainDlgProc(HWND hwnd, UINT msg,
                create_controls(hwnd, dlgtype, tunnelspanelstart);
            if (!strcmp(buffer, "Connection"))
                create_controls(hwnd, dlgtype, connectionpanelstart);
+           if (!strcmp(buffer, "Proxy"))
+               create_controls(hwnd, dlgtype, proxypanelstart);
            if (!strcmp(buffer, "Telnet"))
                create_controls(hwnd, dlgtype, telnetpanelstart);
            if (!strcmp(buffer, "Rlogin"))
@@ -1966,6 +2298,8 @@ static int GenericMainDlgProc(HWND hwnd, UINT msg,
                create_controls(hwnd, dlgtype, sshpanelstart);
            if (!strcmp(buffer, "Auth"))
                create_controls(hwnd, dlgtype, sshauthpanelstart);
+           if (!strcmp(buffer, "Bugs"))
+               create_controls(hwnd, dlgtype, sshbugspanelstart);
            if (!strcmp(buffer, "Selection"))
                create_controls(hwnd, dlgtype, selectionpanelstart);
            if (!strcmp(buffer, "Colours"))
@@ -2103,20 +2437,20 @@ static int GenericMainDlgProc(HWND hwnd, UINT msg,
                            MessageBeep(0);
                            break;
                        }
-                       strcpy(str, sessions[n]);
+                       strcpy(str, sesslist.sessions[n]);
                    }
                    save_settings(str, !!strcmp(str, "Default Settings"),
                                  &cfg);
-                   get_sesslist(FALSE);
-                   get_sesslist(TRUE);
+                   get_sesslist(&sesslist, FALSE);
+                   get_sesslist(&sesslist, TRUE);
                    SendDlgItemMessage(hwnd, IDC_SESSLIST, WM_SETREDRAW,
                                       FALSE, 0);
                    SendDlgItemMessage(hwnd, IDC_SESSLIST, LB_RESETCONTENT,
                                       0, 0);
-                   for (i = 0; i < nsessions; i++)
+                   for (i = 0; i < sesslist.nsessions; i++)
                        SendDlgItemMessage(hwnd, IDC_SESSLIST,
                                           LB_ADDSTRING, 0,
-                                          (LPARAM) (sessions[i]));
+                                          (LPARAM) (sesslist.sessions[i]));
                    SendDlgItemMessage(hwnd, IDC_SESSLIST, LB_SETCURSEL,
                                       (WPARAM) - 1, 0);
                    SendDlgItemMessage(hwnd, IDC_SESSLIST, WM_SETREDRAW,
@@ -2162,17 +2496,17 @@ static int GenericMainDlgProc(HWND hwnd, UINT msg,
                        MessageBeep(0);
                        break;
                    }
-                   del_settings(sessions[n]);
-                   get_sesslist(FALSE);
-                   get_sesslist(TRUE);
+                   del_settings(sesslist.sessions[n]);
+                   get_sesslist(&sesslist, FALSE);
+                   get_sesslist(&sesslist, TRUE);
                    SendDlgItemMessage(hwnd, IDC_SESSLIST, WM_SETREDRAW,
                                       FALSE, 0);
                    SendDlgItemMessage(hwnd, IDC_SESSLIST, LB_RESETCONTENT,
                                       0, 0);
-                   for (i = 0; i < nsessions; i++)
+                   for (i = 0; i < sesslist.nsessions; i++)
                        SendDlgItemMessage(hwnd, IDC_SESSLIST,
                                           LB_ADDSTRING, 0,
-                                          (LPARAM) (sessions[i]));
+                                          (LPARAM) (sesslist.sessions[i]));
                    SendDlgItemMessage(hwnd, IDC_SESSLIST, LB_SETCURSEL,
                                       (WPARAM) - 1, 0);
                    SendDlgItemMessage(hwnd, IDC_SESSLIST, WM_SETREDRAW,
@@ -2269,6 +2603,42 @@ static int GenericMainDlgProc(HWND hwnd, UINT msg,
                        cfg.no_applic_k =
                        IsDlgButtonChecked(hwnd, IDC_NOAPPLICK);
                break;
+             case IDC_NOMOUSEREP:
+               if (HIWORD(wParam) == BN_CLICKED ||
+                   HIWORD(wParam) == BN_DOUBLECLICKED)
+                       cfg.no_mouse_rep =
+                       IsDlgButtonChecked(hwnd, IDC_NOMOUSEREP);
+               break;
+             case IDC_NORESIZE:
+               if (HIWORD(wParam) == BN_CLICKED ||
+                   HIWORD(wParam) == BN_DOUBLECLICKED)
+                       cfg.no_remote_resize =
+                       IsDlgButtonChecked(hwnd, IDC_NORESIZE);
+               break;
+             case IDC_NOALTSCREEN:
+               if (HIWORD(wParam) == BN_CLICKED ||
+                   HIWORD(wParam) == BN_DOUBLECLICKED)
+                       cfg.no_alt_screen =
+                       IsDlgButtonChecked(hwnd, IDC_NOALTSCREEN);
+               break;
+             case IDC_NOWINTITLE:
+               if (HIWORD(wParam) == BN_CLICKED ||
+                   HIWORD(wParam) == BN_DOUBLECLICKED)
+                       cfg.no_remote_wintitle =
+                       IsDlgButtonChecked(hwnd, IDC_NOWINTITLE);
+               break;
+             case IDC_NODBACKSPACE:
+               if (HIWORD(wParam) == BN_CLICKED ||
+                   HIWORD(wParam) == BN_DOUBLECLICKED)
+                       cfg.no_dbackspace =
+                       IsDlgButtonChecked(hwnd, IDC_NODBACKSPACE);
+               break;
+             case IDC_NOCHARSET:
+               if (HIWORD(wParam) == BN_CLICKED ||
+                   HIWORD(wParam) == BN_DOUBLECLICKED)
+                       cfg.no_remote_charset =
+                       IsDlgButtonChecked(hwnd, IDC_NOCHARSET);
+               break;
              case IDC_ALTF4:
                if (HIWORD(wParam) == BN_CLICKED ||
                    HIWORD(wParam) == BN_DOUBLECLICKED)
@@ -2623,6 +2993,90 @@ static int GenericMainDlgProc(HWND hwnd, UINT msg,
                    GetDlgItemText(hwnd, IDC_TTEDIT, cfg.termtype,
                                   sizeof(cfg.termtype) - 1);
                break;
+
+               /* proxy config */
+             case IDC_PROXYHOSTEDIT:
+               if (HIWORD(wParam) == EN_CHANGE)
+                   GetDlgItemText(hwnd, IDC_PROXYHOSTEDIT, cfg.proxy_host, 
+                                  sizeof(cfg.proxy_host) - 1);
+               break;
+             case IDC_PROXYPORTEDIT:
+               if (HIWORD(wParam) == EN_CHANGE) {
+                   GetDlgItemText(hwnd, IDC_PROXYPORTEDIT, portname, 31);
+                   if (isdigit(portname[0]))
+                       MyGetDlgItemInt(hwnd, IDC_PROXYPORTEDIT, &cfg.proxy_port);
+                   else {
+                       service = getservbyname(portname, NULL);
+                       if (service)
+                           cfg.proxy_port = ntohs(service->s_port);
+                       else
+                           cfg.proxy_port = 0;
+                   }
+               }
+               break;
+             case IDC_PROXYEXCLUDEEDIT:
+               if (HIWORD(wParam) == EN_CHANGE)
+                   GetDlgItemText(hwnd, IDC_PROXYEXCLUDEEDIT,
+                                  cfg.proxy_exclude_list,
+                                  sizeof(cfg.proxy_exclude_list) - 1);
+               break;
+             case IDC_PROXYUSEREDIT:
+               if (HIWORD(wParam) == EN_CHANGE)
+                   GetDlgItemText(hwnd, IDC_PROXYUSEREDIT,
+                                  cfg.proxy_username, 
+                                  sizeof(cfg.proxy_username) - 1);
+               break;
+             case IDC_PROXYPASSEDIT:
+               if (HIWORD(wParam) == EN_CHANGE)
+                   GetDlgItemText(hwnd, IDC_PROXYPASSEDIT,
+                                  cfg.proxy_password, 
+                                  sizeof(cfg.proxy_password) - 1);
+               break;
+             case IDC_PROXYTELNETCMDEDIT:
+               if (HIWORD(wParam) == EN_CHANGE)
+                   GetDlgItemText(hwnd, IDC_PROXYTELNETCMDEDIT,
+                                  cfg.proxy_telnet_command,
+                                  sizeof(cfg.proxy_telnet_command) - 1);
+               break;
+             case IDC_PROXYSOCKSVER5:
+             case IDC_PROXYSOCKSVER4:
+               if (HIWORD(wParam) == BN_CLICKED ||
+                   HIWORD(wParam) == BN_DOUBLECLICKED) {
+                   cfg.proxy_socks_version =
+                       IsDlgButtonChecked(hwnd, IDC_PROXYSOCKSVER4) ? 4 : 5;
+               }
+               break;
+             case IDC_PROXYLOCALHOST:
+               if (HIWORD(wParam) == BN_CLICKED ||
+                   HIWORD(wParam) == BN_DOUBLECLICKED)
+                   cfg.even_proxy_localhost =
+                   IsDlgButtonChecked(hwnd, IDC_PROXYLOCALHOST);
+               break;
+             case IDC_PROXYDNSNO:
+             case IDC_PROXYDNSAUTO:
+             case IDC_PROXYDNSYES:
+               if (HIWORD(wParam) == BN_CLICKED ||
+                   HIWORD(wParam) == BN_DOUBLECLICKED) {
+                   cfg.proxy_dns =
+                       IsDlgButtonChecked(hwnd, IDC_PROXYDNSNO) ? PROXYDNS_NO :
+                       IsDlgButtonChecked(hwnd, IDC_PROXYDNSYES) ? PROXYDNS_YES :
+                       PROXYDNS_AUTO;
+               }
+               break;
+             case IDC_PROXYTYPENONE:
+             case IDC_PROXYTYPEHTTP:
+             case IDC_PROXYTYPESOCKS:
+             case IDC_PROXYTYPETELNET:
+               if (HIWORD(wParam) == BN_CLICKED ||
+                   HIWORD(wParam) == BN_DOUBLECLICKED) {
+                   cfg.proxy_type =
+                       IsDlgButtonChecked(hwnd, IDC_PROXYTYPEHTTP) ? PROXY_HTTP :
+                       IsDlgButtonChecked(hwnd, IDC_PROXYTYPESOCKS) ? PROXY_SOCKS :
+                       IsDlgButtonChecked(hwnd, IDC_PROXYTYPETELNET) ? PROXY_TELNET :
+                       PROXY_NONE;
+               }
+               break;
+
              case IDC_LGFEDIT:
                if (HIWORD(wParam) == EN_CHANGE)
                    GetDlgItemText(hwnd, IDC_LGFEDIT, cfg.logfilename,
@@ -2793,12 +3247,6 @@ static int GenericMainDlgProc(HWND hwnd, UINT msg,
                        cfg.compression =
                        IsDlgButtonChecked(hwnd, IDC_COMPRESS);
                break;
-             case IDC_BUGGYMAC:
-               if (HIWORD(wParam) == BN_CLICKED ||
-                   HIWORD(wParam) == BN_DOUBLECLICKED)
-                       cfg.buggymac =
-                       IsDlgButtonChecked(hwnd, IDC_BUGGYMAC);
-               break;
              case IDC_SSH2DES:
                if (HIWORD(wParam) == BN_CLICKED ||
                    HIWORD(wParam) == BN_DOUBLECLICKED)
@@ -2824,14 +3272,20 @@ static int GenericMainDlgProc(HWND hwnd, UINT msg,
                                 cfg.ssh_cipherlist, CIPHER_MAX,
                                 0, hwnd, wParam, lParam);
                break;
+             case IDC_SSHPROT1ONLY:
              case IDC_SSHPROT1:
              case IDC_SSHPROT2:
+             case IDC_SSHPROT2ONLY:
                if (HIWORD(wParam) == BN_CLICKED ||
                    HIWORD(wParam) == BN_DOUBLECLICKED) {
+                   if (IsDlgButtonChecked(hwnd, IDC_SSHPROT1ONLY))
+                       cfg.sshprot = 0;
                    if (IsDlgButtonChecked(hwnd, IDC_SSHPROT1))
                        cfg.sshprot = 1;
                    else if (IsDlgButtonChecked(hwnd, IDC_SSHPROT2))
                        cfg.sshprot = 2;
+                   else if (IsDlgButtonChecked(hwnd, IDC_SSHPROT2ONLY))
+                       cfg.sshprot = 3;
                }
                break;
              case IDC_AUTHTIS:
@@ -2864,7 +3318,8 @@ static int GenericMainDlgProc(HWND hwnd, UINT msg,
                of.lStructSize = sizeof(of);
 #endif
                of.hwndOwner = hwnd;
-               of.lpstrFilter = "All Files\0*\0\0\0";
+               of.lpstrFilter = "PuTTY Private Key Files\0*.PPK\0"
+                   "AllFiles\0*\0\0\0";
                of.lpstrCustomFilter = NULL;
                of.nFilterIndex = 1;
                of.lpstrFile = filename;
@@ -3022,6 +3477,19 @@ static int GenericMainDlgProc(HWND hwnd, UINT msg,
                    SetDlgItemText(hwnd, IDC_CODEPAGE, cfg.line_codepage);
                }
                break;
+             case IDC_PRINTER:
+               if (HIWORD(wParam) == CBN_SELCHANGE) {
+                   int index = SendDlgItemMessage(hwnd, IDC_PRINTER,
+                                                  CB_GETCURSEL, 0, 0);
+                   SendDlgItemMessage(hwnd, IDC_PRINTER, CB_GETLBTEXT,
+                                      index, (LPARAM)cfg.printer);
+               } else if (HIWORD(wParam) == CBN_EDITCHANGE) {
+                   GetDlgItemText(hwnd, IDC_PRINTER, cfg.printer,
+                                  sizeof(cfg.printer) - 1);
+               }
+               if (!strcmp(cfg.printer, PRINTER_DISABLED_STRING))
+                   *cfg.printer = '\0';
+               break;
              case IDC_CAPSLOCKCYR:
                if (HIWORD(wParam) == BN_CLICKED ||
                    HIWORD(wParam) == BN_DOUBLECLICKED) {
@@ -3151,6 +3619,62 @@ static int GenericMainDlgProc(HWND hwnd, UINT msg,
                  disaster2:;
                }
                break;
+             case IDC_BUGD_IGNORE1:
+               if (HIWORD(wParam) == CBN_SELCHANGE) {
+                   int index = SendDlgItemMessage(hwnd, IDC_BUGD_IGNORE1,
+                                                  CB_GETCURSEL, 0, 0);
+                   cfg.sshbug_ignore1 = (index == 0 ? BUG_AUTO :
+                                         index == 1 ? BUG_OFF : BUG_ON);
+               }
+               break;
+             case IDC_BUGD_PLAINPW1:
+               if (HIWORD(wParam) == CBN_SELCHANGE) {
+                   int index = SendDlgItemMessage(hwnd, IDC_BUGD_PLAINPW1,
+                                                  CB_GETCURSEL, 0, 0);
+                   cfg.sshbug_plainpw1 = (index == 0 ? BUG_AUTO :
+                                          index == 1 ? BUG_OFF : BUG_ON);
+               }
+               break;
+             case IDC_BUGD_RSA1:
+               if (HIWORD(wParam) == CBN_SELCHANGE) {
+                   int index = SendDlgItemMessage(hwnd, IDC_BUGD_RSA1,
+                                                  CB_GETCURSEL, 0, 0);
+                   cfg.sshbug_rsa1 = (index == 0 ? BUG_AUTO :
+                                      index == 1 ? BUG_OFF : BUG_ON);
+               }
+               break;
+             case IDC_BUGD_HMAC2:
+               if (HIWORD(wParam) == CBN_SELCHANGE) {
+                   int index = SendDlgItemMessage(hwnd, IDC_BUGD_HMAC2,
+                                                  CB_GETCURSEL, 0, 0);
+                   cfg.sshbug_hmac2 = (index == 0 ? BUG_AUTO :
+                                       index == 1 ? BUG_OFF : BUG_ON);
+               }
+               break;
+             case IDC_BUGD_DERIVEKEY2:
+               if (HIWORD(wParam) == CBN_SELCHANGE) {
+                   int index = SendDlgItemMessage(hwnd, IDC_BUGD_DERIVEKEY2,
+                                                  CB_GETCURSEL, 0, 0);
+                   cfg.sshbug_derivekey2 = (index == 0 ? BUG_AUTO :
+                                            index == 1 ? BUG_OFF : BUG_ON);
+               }
+               break;
+             case IDC_BUGD_RSAPAD2:
+               if (HIWORD(wParam) == CBN_SELCHANGE) {
+                   int index = SendDlgItemMessage(hwnd, IDC_BUGD_RSAPAD2,
+                                                  CB_GETCURSEL, 0, 0);
+                   cfg.sshbug_rsapad2 = (index == 0 ? BUG_AUTO :
+                                         index == 1 ? BUG_OFF : BUG_ON);
+               }
+               break;
+             case IDC_BUGD_DHGEX2:
+               if (HIWORD(wParam) == CBN_SELCHANGE) {
+                   int index = SendDlgItemMessage(hwnd, IDC_BUGD_DHGEX2,
+                                                  CB_GETCURSEL, 0, 0);
+                   cfg.sshbug_dhgex2 = (index == 0 ? BUG_AUTO :
+                                        index == 1 ? BUG_OFF : BUG_ON);
+               }
+               break;
            }
        return 0;
       case WM_HELP:
@@ -3243,11 +3767,11 @@ int do_config(void)
 {
     int ret;
 
-    get_sesslist(TRUE);
+    get_sesslist(&sesslist, TRUE);
     savedsession[0] = '\0';
     ret =
        DialogBox(hinst, MAKEINTRESOURCE(IDD_MAINBOX), NULL, MainDlgProc);
-    get_sesslist(FALSE);
+    get_sesslist(&sesslist, FALSE);
 
     return ret;
 }
@@ -3266,11 +3790,13 @@ int do_reconfig(HWND hwnd)
     return ret;
 }
 
-void logevent(char *string)
+void logevent(void *frontend, char *string)
 {
     char timebuf[40];
     time_t t;
 
+    log_eventlog(logctx, string);
+
     if (nevents >= negsize) {
        negsize += 64;
        events = srealloc(events, negsize * sizeof(*events));
@@ -3308,7 +3834,7 @@ void showabout(HWND hwnd)
     DialogBox(hinst, MAKEINTRESOURCE(IDD_ABOUTBOX), hwnd, AboutProc);
 }
 
-void verify_ssh_host_key(char *host, int port, char *keytype,
+void verify_ssh_host_key(void *frontend, char *host, int port, char *keytype,
                         char *keystr, char *fingerprint)
 {
     int ret;
@@ -3365,7 +3891,7 @@ void verify_ssh_host_key(char *host, int port, char *keytype,
        if (mbret == IDYES)
            store_host_key(host, port, keytype, keystr);
        if (mbret == IDCANCEL)
-           exit(0);
+           cleanup_exit(0);
     }
     if (ret == 1) {                   /* key was absent */
        int mbret;
@@ -3375,7 +3901,7 @@ void verify_ssh_host_key(char *host, int port, char *keytype,
        if (mbret == IDYES)
            store_host_key(host, port, keytype, keystr);
        if (mbret == IDCANCEL)
-           exit(0);
+           cleanup_exit(0);
     }
 }
 
@@ -3384,7 +3910,7 @@ void verify_ssh_host_key(char *host, int port, char *keytype,
  * below the configured 'warn' threshold).
  * cs: 0 = both ways, 1 = client->server, 2 = server->client
  */
-void askcipher(char *ciphername, int cs)
+void askcipher(void *frontend, char *ciphername, int cs)
 {
     static const char mbtitle[] = "PuTTY Security Alert";
     static const char msg[] =
@@ -3406,14 +3932,14 @@ void askcipher(char *ciphername, int cs)
     if (mbret == IDYES)
        return;
     else
-       exit(0);
+       cleanup_exit(0);
 }
 
 /*
  * 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).
  */
-int askappend(char *filename)
+int askappend(void *frontend, char *filename)
 {
     static const char mbtitle[] = "PuTTY Log to File";
     static const char msgtemplate[] =
@@ -3442,6 +3968,13 @@ int askappend(char *filename)
 
 /*
  * Warn about the obsolescent key file format.
+ * 
+ * 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.
  */
 void old_keyfile_warning(void)
 {