PSCP: After a password supplied with `-pw' fails to authenticate,
[u/mdw/putty] / windlg.c
CommitLineData
374330e2 1#include <windows.h>
2#include <commctrl.h>
3#include <commdlg.h>
4#include <winsock.h>
5#include <stdio.h>
6#include <stdlib.h>
7
374330e2 8#include "ssh.h"
bea1ef5f 9#include "putty.h"
374330e2 10#include "win_res.h"
11
14963b8f 12#define NPANELS 8
13#define MAIN_NPANELS 8
14#define RECONF_NPANELS 5
374330e2 15
16static const char *const puttystr = PUTTY_REG_POS "\\Sessions";
17
c5e9c988 18static char **events = NULL;
19static int nevents = 0, negsize = 0;
20
374330e2 21static HWND logbox = NULL, abtbox = NULL;
22
23static char hex[16] = "0123456789ABCDEF";
24
25static void mungestr(char *in, char *out) {
26 int candot = 0;
27
28 while (*in) {
29 if (*in == ' ' || *in == '\\' || *in == '*' || *in == '?' ||
30 *in == '%' || *in < ' ' || *in > '~' || (*in == '.' && !candot)) {
31 *out++ = '%';
32 *out++ = hex[((unsigned char)*in) >> 4];
33 *out++ = hex[((unsigned char)*in) & 15];
34 } else
35 *out++ = *in;
36 in++;
37 candot = 1;
38 }
39 *out = '\0';
40 return;
41}
42
43static void unmungestr(char *in, char *out) {
374330e2 44 while (*in) {
45 if (*in == '%' && in[1] && in[2]) {
46 int i, j;
47
48 i = in[1] - '0'; i -= (i > 9 ? 7 : 0);
49 j = in[2] - '0'; j -= (j > 9 ? 7 : 0);
50
51 *out++ = (i<<4) + j;
52 in += 3;
53 } else
54 *out++ = *in++;
55 }
56 *out = '\0';
57 return;
58}
59
60static void wpps(HKEY key, LPCTSTR name, LPCTSTR value) {
61 RegSetValueEx(key, name, 0, REG_SZ, value, 1+strlen(value));
62}
63
64static void wppi(HKEY key, LPCTSTR name, int value) {
65 RegSetValueEx(key, name, 0, REG_DWORD,
66 (CONST BYTE *)&value, sizeof(value));
67}
68
69static void gpps(HKEY key, LPCTSTR name, LPCTSTR def,
70 LPTSTR val, int len) {
71 DWORD type, size;
72 size = len;
73
74 if (key == NULL ||
75 RegQueryValueEx(key, name, 0, &type, val, &size) != ERROR_SUCCESS ||
76 type != REG_SZ) {
77 strncpy(val, def, len);
78 val[len-1] = '\0';
79 }
80}
81
82static void gppi(HKEY key, LPCTSTR name, int def, int *i) {
83 DWORD type, val, size;
84 size = sizeof(val);
85
86 if (key == NULL ||
87 RegQueryValueEx(key, name, 0, &type,
88 (BYTE *)&val, &size) != ERROR_SUCCESS ||
89 size != sizeof(val) || type != REG_DWORD)
90 *i = def;
91 else
92 *i = val;
93}
94
374330e2 95static HINSTANCE hinst;
96
1cd246bb 97static int readytogo;
98
374330e2 99static void save_settings (char *section, int do_host) {
100 int i;
101 HKEY subkey1, sesskey;
102 char *p;
103
104 p = malloc(3*strlen(section)+1);
105 mungestr(section, p);
106
107 if (RegCreateKey(HKEY_CURRENT_USER, puttystr, &subkey1)!=ERROR_SUCCESS ||
108 RegCreateKey(subkey1, p, &sesskey) != ERROR_SUCCESS) {
374330e2 109 sesskey = NULL;
110 }
111
112 free(p);
113 RegCloseKey(subkey1);
114
115 wppi (sesskey, "Present", 1);
116 if (do_host) {
117 wpps (sesskey, "HostName", cfg.host);
118 wppi (sesskey, "PortNumber", cfg.port);
89ee5268 119 p = "raw";
a721b9eb 120 for (i = 0; backends[i].name != NULL; i++)
89ee5268 121 if (backends[i].protocol == cfg.protocol) {
122 p = backends[i].name;
123 break;
124 }
125 wpps (sesskey, "Protocol", p);
374330e2 126 }
127 wppi (sesskey, "CloseOnExit", !!cfg.close_on_exit);
9ef49106 128 wppi (sesskey, "WarnOnClose", !!cfg.warn_on_close);
374330e2 129 wpps (sesskey, "TerminalType", cfg.termtype);
130 wpps (sesskey, "TerminalSpeed", cfg.termspeed);
131 {
37508af4 132 char buf[2*sizeof(cfg.environmt)], *p, *q;
374330e2 133 p = buf;
37508af4 134 q = cfg.environmt;
374330e2 135 while (*q) {
136 while (*q) {
137 int c = *q++;
138 if (c == '=' || c == ',' || c == '\\')
139 *p++ = '\\';
140 if (c == '\t')
141 c = '=';
142 *p++ = c;
143 }
144 *p++ = ',';
145 q++;
146 }
147 *p = '\0';
148 wpps (sesskey, "Environment", buf);
149 }
150 wpps (sesskey, "UserName", cfg.username);
fef97f43 151 wppi (sesskey, "NoPTY", cfg.nopty);
bea1ef5f 152 wpps (sesskey, "Cipher", cfg.cipher == CIPHER_BLOWFISH ? "blowfish" :
9697bfd2 153 cfg.cipher == CIPHER_DES ? "des" : "3des");
ccbfb941 154 wppi (sesskey, "AuthTIS", cfg.try_tis_auth);
374330e2 155 wppi (sesskey, "RFCEnviron", cfg.rfc_environ);
156 wppi (sesskey, "BackspaceIsDelete", cfg.bksp_is_delete);
157 wppi (sesskey, "RXVTHomeEnd", cfg.rxvt_homeend);
158 wppi (sesskey, "LinuxFunctionKeys", cfg.linux_funkeys);
159 wppi (sesskey, "ApplicationCursorKeys", cfg.app_cursor);
160 wppi (sesskey, "ApplicationKeypad", cfg.app_keypad);
c5e9c988 161 wppi (sesskey, "NetHackKeypad", cfg.nethack_keypad);
162 wppi (sesskey, "AltF4", cfg.alt_f4);
163 wppi (sesskey, "AltSpace", cfg.alt_space);
5bc238bb 164 wppi (sesskey, "LdiscTerm", cfg.ldisc_term);
217dceef 165 wppi (sesskey, "BlinkCur", cfg.blink_cur);
2a25a1b4 166 wppi (sesskey, "Beep", cfg.beep);
374330e2 167 wppi (sesskey, "ScrollbackLines", cfg.savelines);
168 wppi (sesskey, "DECOriginMode", cfg.dec_om);
169 wppi (sesskey, "AutoWrapMode", cfg.wrap_mode);
fef97f43 170 wppi (sesskey, "LFImpliesCR", cfg.lfhascr);
374330e2 171 wppi (sesskey, "WinNameAlways", cfg.win_name_always);
172 wppi (sesskey, "TermWidth", cfg.width);
173 wppi (sesskey, "TermHeight", cfg.height);
174 wpps (sesskey, "Font", cfg.font);
175 wppi (sesskey, "FontIsBold", cfg.fontisbold);
14963b8f 176 wppi (sesskey, "FontCharSet", cfg.fontcharset);
374330e2 177 wppi (sesskey, "FontHeight", cfg.fontheight);
178 wppi (sesskey, "FontVTMode", cfg.vtmode);
179 wppi (sesskey, "TryPalette", cfg.try_palette);
180 wppi (sesskey, "BoldAsColour", cfg.bold_colour);
181 for (i=0; i<22; i++) {
182 char buf[20], buf2[30];
183 sprintf(buf, "Colour%d", i);
184 sprintf(buf2, "%d,%d,%d", cfg.colours[i][0],
185 cfg.colours[i][1], cfg.colours[i][2]);
186 wpps (sesskey, buf, buf2);
187 }
188 wppi (sesskey, "MouseIsXterm", cfg.mouse_is_xterm);
189 for (i=0; i<256; i+=32) {
190 char buf[20], buf2[256];
191 int j;
192 sprintf(buf, "Wordness%d", i);
193 *buf2 = '\0';
194 for (j=i; j<i+32; j++) {
195 sprintf(buf2+strlen(buf2), "%s%d",
196 (*buf2 ? "," : ""), cfg.wordness[j]);
197 }
198 wpps (sesskey, buf, buf2);
199 }
14963b8f 200 wppi (sesskey, "KoiWinXlat", cfg.xlat_enablekoiwin);
d3d16feb 201 wppi (sesskey, "88592Xlat", cfg.xlat_88592w1250);
14963b8f 202 wppi (sesskey, "CapsLockCyr", cfg.xlat_capslockcyr);
374330e2 203
204 RegCloseKey(sesskey);
205}
206
207static void del_session (char *section) {
208 HKEY subkey1;
209 char *p;
210
211 if (RegOpenKey(HKEY_CURRENT_USER, puttystr, &subkey1) != ERROR_SUCCESS)
212 return;
213
214 p = malloc(3*strlen(section)+1);
215 mungestr(section, p);
216 RegDeleteKey(subkey1, p);
217 free(p);
218
219 RegCloseKey(subkey1);
220}
221
222static void load_settings (char *section, int do_host) {
223 int i;
224 HKEY subkey1, sesskey;
225 char *p;
e277c42d 226 char prot[10];
374330e2 227
228 p = malloc(3*strlen(section)+1);
229 mungestr(section, p);
9816085c 230
231 if (RegOpenKey(HKEY_CURRENT_USER, puttystr, &subkey1) != ERROR_SUCCESS) {
374330e2 232 sesskey = NULL;
9816085c 233 } else {
234 if (RegOpenKey(subkey1, p, &sesskey) != ERROR_SUCCESS) {
235 sesskey = NULL;
236 }
237 RegCloseKey(subkey1);
374330e2 238 }
239
240 free(p);
374330e2 241
e277c42d 242 gpps (sesskey, "HostName", "", cfg.host, sizeof(cfg.host));
243 gppi (sesskey, "PortNumber", default_port, &cfg.port);
89ee5268 244
e277c42d 245 gpps (sesskey, "Protocol", "default", prot, 10);
89ee5268 246 cfg.protocol = default_protocol;
a721b9eb 247 for (i = 0; backends[i].name != NULL; i++)
89ee5268 248 if (!strcmp(prot, backends[i].name)) {
249 cfg.protocol = backends[i].protocol;
250 break;
251 }
e277c42d 252
374330e2 253 gppi (sesskey, "CloseOnExit", 1, &cfg.close_on_exit);
9ef49106 254 gppi (sesskey, "WarnOnClose", 1, &cfg.warn_on_close);
374330e2 255 gpps (sesskey, "TerminalType", "xterm", cfg.termtype,
256 sizeof(cfg.termtype));
257 gpps (sesskey, "TerminalSpeed", "38400,38400", cfg.termspeed,
258 sizeof(cfg.termspeed));
259 {
37508af4 260 char buf[2*sizeof(cfg.environmt)], *p, *q;
374330e2 261 gpps (sesskey, "Environment", "", buf, sizeof(buf));
262 p = buf;
29b611b7 263 q = cfg.environmt;
374330e2 264 while (*p) {
265 while (*p && *p != ',') {
266 int c = *p++;
267 if (c == '=')
268 c = '\t';
269 if (c == '\\')
270 c = *p++;
29b611b7 271 *q++ = c;
374330e2 272 }
273 if (*p == ',') p++;
274 *q++ = '\0';
275 }
276 *q = '\0';
277 }
278 gpps (sesskey, "UserName", "", cfg.username, sizeof(cfg.username));
fef97f43 279 gppi (sesskey, "NoPTY", 0, &cfg.nopty);
bea1ef5f 280 {
281 char cipher[10];
282 gpps (sesskey, "Cipher", "3des", cipher, 10);
283 if (!strcmp(cipher, "blowfish"))
284 cfg.cipher = CIPHER_BLOWFISH;
9697bfd2 285 else if (!strcmp(cipher, "des"))
286 cfg.cipher = CIPHER_DES;
bea1ef5f 287 else
288 cfg.cipher = CIPHER_3DES;
289 }
ccbfb941 290 gppi (sesskey, "AuthTIS", 0, &cfg.try_tis_auth);
374330e2 291 gppi (sesskey, "RFCEnviron", 0, &cfg.rfc_environ);
292 gppi (sesskey, "BackspaceIsDelete", 1, &cfg.bksp_is_delete);
293 gppi (sesskey, "RXVTHomeEnd", 0, &cfg.rxvt_homeend);
294 gppi (sesskey, "LinuxFunctionKeys", 0, &cfg.linux_funkeys);
295 gppi (sesskey, "ApplicationCursorKeys", 0, &cfg.app_cursor);
296 gppi (sesskey, "ApplicationKeypad", 0, &cfg.app_keypad);
c5e9c988 297 gppi (sesskey, "NetHackKeypad", 0, &cfg.nethack_keypad);
298 gppi (sesskey, "AltF4", 1, &cfg.alt_f4);
299 gppi (sesskey, "AltSpace", 0, &cfg.alt_space);
5bc238bb 300 gppi (sesskey, "LdiscTerm", 0, &cfg.ldisc_term);
217dceef 301 gppi (sesskey, "BlinkCur", 0, &cfg.blink_cur);
2a25a1b4 302 gppi (sesskey, "Beep", 1, &cfg.beep);
374330e2 303 gppi (sesskey, "ScrollbackLines", 200, &cfg.savelines);
304 gppi (sesskey, "DECOriginMode", 0, &cfg.dec_om);
305 gppi (sesskey, "AutoWrapMode", 1, &cfg.wrap_mode);
fef97f43 306 gppi (sesskey, "LFImpliesCR", 0, &cfg.lfhascr);
374330e2 307 gppi (sesskey, "WinNameAlways", 0, &cfg.win_name_always);
308 gppi (sesskey, "TermWidth", 80, &cfg.width);
309 gppi (sesskey, "TermHeight", 24, &cfg.height);
310 gpps (sesskey, "Font", "Courier", cfg.font, sizeof(cfg.font));
311 gppi (sesskey, "FontIsBold", 0, &cfg.fontisbold);
14963b8f 312 gppi (sesskey, "FontCharSet", ANSI_CHARSET, &cfg.fontcharset);
374330e2 313 gppi (sesskey, "FontHeight", 10, &cfg.fontheight);
2a7bfc6e 314 gppi (sesskey, "FontVTMode", VT_OEMANSI, (int *)&cfg.vtmode);
374330e2 315 gppi (sesskey, "TryPalette", 0, &cfg.try_palette);
316 gppi (sesskey, "BoldAsColour", 1, &cfg.bold_colour);
317 for (i=0; i<22; i++) {
318 static char *defaults[] = {
319 "187,187,187", "255,255,255", "0,0,0", "85,85,85", "0,0,0",
320 "0,255,0", "0,0,0", "85,85,85", "187,0,0", "255,85,85",
321 "0,187,0", "85,255,85", "187,187,0", "255,255,85", "0,0,187",
322 "85,85,255", "187,0,187", "255,85,255", "0,187,187",
323 "85,255,255", "187,187,187", "255,255,255"
324 };
325 char buf[20], buf2[30];
1d470ad2 326 int c0, c1, c2;
374330e2 327 sprintf(buf, "Colour%d", i);
328 gpps (sesskey, buf, defaults[i], buf2, sizeof(buf2));
1d470ad2 329 if(sscanf(buf2, "%d,%d,%d", &c0, &c1, &c2) == 3) {
330 cfg.colours[i][0] = c0;
331 cfg.colours[i][1] = c1;
332 cfg.colours[i][2] = c2;
333 }
374330e2 334 }
335 gppi (sesskey, "MouseIsXterm", 0, &cfg.mouse_is_xterm);
336 for (i=0; i<256; i+=32) {
337 static char *defaults[] = {
338 "0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0",
339 "0,1,2,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,2,2,1,1,1,1,1,1",
340 "1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,1,1,1,1,2",
341 "1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,1,1,1,1,1",
342 "1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1",
343 "1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1",
344 "2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,2,2,2",
345 "2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,2,2,2"
346 };
347 char buf[20], buf2[256], *p;
348 int j;
349 sprintf(buf, "Wordness%d", i);
350 gpps (sesskey, buf, defaults[i/32], buf2, sizeof(buf2));
351 p = buf2;
352 for (j=i; j<i+32; j++) {
353 char *q = p;
354 while (*p && *p != ',') p++;
355 if (*p == ',') *p++ = '\0';
356 cfg.wordness[j] = atoi(q);
357 }
358 }
14963b8f 359 gppi (sesskey, "KoiWinXlat", 0, &cfg.xlat_enablekoiwin);
d3d16feb 360 gppi (sesskey, "88592Xlat", 0, &cfg.xlat_88592w1250);
14963b8f 361 gppi (sesskey, "CapsLockCyr", 0, &cfg.xlat_capslockcyr);
362
374330e2 363 RegCloseKey(sesskey);
364}
365
366static void MyGetDlgItemInt (HWND hwnd, int id, int *result) {
367 BOOL ok;
368 int n;
369 n = GetDlgItemInt (hwnd, id, &ok, FALSE);
370 if (ok)
371 *result = n;
372}
373
374static int CALLBACK LogProc (HWND hwnd, UINT msg,
375 WPARAM wParam, LPARAM lParam) {
376 int i;
377
378 switch (msg) {
379 case WM_INITDIALOG:
c5e9c988 380 for (i=0; i<nevents; i++)
374330e2 381 SendDlgItemMessage (hwnd, IDN_LIST, LB_ADDSTRING,
c5e9c988 382 0, (LPARAM)events[i]);
374330e2 383 return 1;
384/* case WM_CTLCOLORDLG: */
385/* return (int) GetStockObject (LTGRAY_BRUSH); */
386 case WM_COMMAND:
387 switch (LOWORD(wParam)) {
388 case IDOK:
389 logbox = NULL;
390 DestroyWindow (hwnd);
391 return 0;
392 }
393 return 0;
394 case WM_CLOSE:
395 logbox = NULL;
396 DestroyWindow (hwnd);
397 return 0;
398 }
399 return 0;
400}
401
d57835ab 402static int CALLBACK LicenceProc (HWND hwnd, UINT msg,
403 WPARAM wParam, LPARAM lParam) {
404 switch (msg) {
405 case WM_INITDIALOG:
406 return 1;
407 case WM_COMMAND:
408 switch (LOWORD(wParam)) {
409 case IDOK:
410 abtbox = NULL;
411 DestroyWindow (hwnd);
412 return 0;
413 }
414 return 0;
415 case WM_CLOSE:
416 abtbox = NULL;
417 DestroyWindow (hwnd);
418 return 0;
419 }
420 return 0;
421}
422
374330e2 423static int CALLBACK AboutProc (HWND hwnd, UINT msg,
424 WPARAM wParam, LPARAM lParam) {
425 switch (msg) {
426 case WM_INITDIALOG:
067a15ea 427 SetDlgItemText (hwnd, IDA_VERSION, ver);
374330e2 428 return 1;
429/* case WM_CTLCOLORDLG: */
430/* return (int) GetStockObject (LTGRAY_BRUSH); */
431/* case WM_CTLCOLORSTATIC: */
432/* SetBkColor ((HDC)wParam, RGB(192,192,192)); */
433/* return (int) GetStockObject (LTGRAY_BRUSH); */
434 case WM_COMMAND:
435 switch (LOWORD(wParam)) {
436 case IDOK:
437 abtbox = NULL;
438 DestroyWindow (hwnd);
439 return 0;
440 case IDA_LICENCE:
441 EnableWindow(hwnd, 0);
442 DialogBox (hinst, MAKEINTRESOURCE(IDD_LICENCEBOX),
d57835ab 443 NULL, LicenceProc);
374330e2 444 EnableWindow(hwnd, 1);
445 return 0;
446 }
447 return 0;
448 case WM_CLOSE:
449 abtbox = NULL;
450 DestroyWindow (hwnd);
451 return 0;
452 }
453 return 0;
454}
455
456static int GeneralPanelProc (HWND hwnd, UINT msg,
457 WPARAM wParam, LPARAM lParam) {
458 switch (msg) {
459 case WM_INITDIALOG:
460 SetWindowPos (hwnd, HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);
461 return 1;
462/* case WM_CTLCOLORDLG: */
463/* return (int) GetStockObject (LTGRAY_BRUSH); */
464/* case WM_CTLCOLORSTATIC: */
465/* case WM_CTLCOLORBTN: */
466/* SetBkColor ((HDC)wParam, RGB(192,192,192)); */
467/* return (int) GetStockObject (LTGRAY_BRUSH); */
468 case WM_CLOSE:
469 DestroyWindow (hwnd);
470 return 1;
471 }
472 return 0;
473}
474
475static int CALLBACK ConnectionProc (HWND hwnd, UINT msg,
476 WPARAM wParam, LPARAM lParam) {
477 int i;
478
479 switch (msg) {
480 case WM_INITDIALOG:
481 SetDlgItemText (hwnd, IDC0_HOST, cfg.host);
482 SetDlgItemInt (hwnd, IDC0_PORT, cfg.port, FALSE);
483 for (i = 0; i < nsessions; i++)
484 SendDlgItemMessage (hwnd, IDC0_SESSLIST, LB_ADDSTRING,
485 0, (LPARAM) (sessions[i]));
5e1a8e27 486 CheckRadioButton (hwnd, IDC0_PROTRAW, IDC0_PROTSSH,
487 cfg.protocol==PROT_SSH ? IDC0_PROTSSH :
488 cfg.protocol==PROT_TELNET ? IDC0_PROTTELNET : IDC0_PROTRAW );
374330e2 489 CheckDlgButton (hwnd, IDC0_CLOSEEXIT, cfg.close_on_exit);
9ef49106 490 CheckDlgButton (hwnd, IDC0_CLOSEWARN, cfg.warn_on_close);
374330e2 491 break;
1cd246bb 492 case WM_LBUTTONUP:
493 /*
494 * Button release should trigger WM_OK if there was a
495 * previous double click on the session list.
496 */
497 ReleaseCapture();
498 if (readytogo)
499 SendMessage (GetParent(hwnd), WM_COMMAND, IDOK, 0);
500 break;
374330e2 501 case WM_COMMAND:
502 switch (LOWORD(wParam)) {
503 case IDC0_PROTTELNET:
504 case IDC0_PROTSSH:
5e1a8e27 505 case IDC0_PROTRAW:
374330e2 506 if (HIWORD(wParam) == BN_CLICKED ||
507 HIWORD(wParam) == BN_DOUBLECLICKED) {
508 int i = IsDlgButtonChecked (hwnd, IDC0_PROTSSH);
5e1a8e27 509 int j = IsDlgButtonChecked (hwnd, IDC0_PROTTELNET);
510 cfg.protocol = i ? PROT_SSH : j ? PROT_TELNET : PROT_RAW ;
374330e2 511 if ((cfg.protocol == PROT_SSH && cfg.port == 23) ||
512 (cfg.protocol == PROT_TELNET && cfg.port == 22)) {
513 cfg.port = i ? 22 : 23;
514 SetDlgItemInt (hwnd, IDC0_PORT, cfg.port, FALSE);
515 }
516 }
517 break;
518 case IDC0_HOST:
519 if (HIWORD(wParam) == EN_CHANGE)
520 GetDlgItemText (hwnd, IDC0_HOST, cfg.host,
521 sizeof(cfg.host)-1);
522 break;
523 case IDC0_PORT:
524 if (HIWORD(wParam) == EN_CHANGE)
525 MyGetDlgItemInt (hwnd, IDC0_PORT, &cfg.port);
526 break;
527 case IDC0_CLOSEEXIT:
528 if (HIWORD(wParam) == BN_CLICKED ||
529 HIWORD(wParam) == BN_DOUBLECLICKED)
530 cfg.close_on_exit = IsDlgButtonChecked (hwnd, IDC0_CLOSEEXIT);
531 break;
9ef49106 532 case IDC0_CLOSEWARN:
533 if (HIWORD(wParam) == BN_CLICKED ||
534 HIWORD(wParam) == BN_DOUBLECLICKED)
535 cfg.warn_on_close = IsDlgButtonChecked (hwnd, IDC0_CLOSEWARN);
536 break;
374330e2 537 case IDC0_SESSEDIT:
538 if (HIWORD(wParam) == EN_CHANGE)
539 SendDlgItemMessage (hwnd, IDC0_SESSLIST, LB_SETCURSEL,
540 (WPARAM) -1, 0);
541 break;
542 case IDC0_SESSSAVE:
543 if (HIWORD(wParam) == BN_CLICKED ||
544 HIWORD(wParam) == BN_DOUBLECLICKED) {
545 /*
546 * Save a session
547 */
548 char str[2048];
549 GetDlgItemText (hwnd, IDC0_SESSEDIT, str, sizeof(str)-1);
550 if (!*str) {
551 int n = SendDlgItemMessage (hwnd, IDC0_SESSLIST,
552 LB_GETCURSEL, 0, 0);
553 if (n == LB_ERR) {
554 MessageBeep(0);
555 break;
556 }
557 strcpy (str, sessions[n]);
558 }
559 save_settings (str, !!strcmp(str, "Default Settings"));
560 get_sesslist (FALSE);
561 get_sesslist (TRUE);
562 SendDlgItemMessage (hwnd, IDC0_SESSLIST, LB_RESETCONTENT,
563 0, 0);
564 for (i = 0; i < nsessions; i++)
565 SendDlgItemMessage (hwnd, IDC0_SESSLIST, LB_ADDSTRING,
566 0, (LPARAM) (sessions[i]));
567 SendDlgItemMessage (hwnd, IDC0_SESSLIST, LB_SETCURSEL,
568 (WPARAM) -1, 0);
569 }
570 break;
571 case IDC0_SESSLIST:
572 case IDC0_SESSLOAD:
573 if (LOWORD(wParam) == IDC0_SESSLOAD &&
574 HIWORD(wParam) != BN_CLICKED &&
575 HIWORD(wParam) != BN_DOUBLECLICKED)
576 break;
577 if (LOWORD(wParam) == IDC0_SESSLIST &&
578 HIWORD(wParam) != LBN_DBLCLK)
579 break;
580 {
581 int n = SendDlgItemMessage (hwnd, IDC0_SESSLIST,
582 LB_GETCURSEL, 0, 0);
583 if (n == LB_ERR) {
584 MessageBeep(0);
585 break;
586 }
587 load_settings (sessions[n],
588 !!strcmp(sessions[n], "Default Settings"));
589 SetDlgItemText (hwnd, IDC0_HOST, cfg.host);
590 SetDlgItemInt (hwnd, IDC0_PORT, cfg.port, FALSE);
5e1a8e27 591 CheckRadioButton (hwnd, IDC0_PROTRAW, IDC0_PROTSSH,
374330e2 592 (cfg.protocol==PROT_SSH ? IDC0_PROTSSH :
5e1a8e27 593 cfg.protocol==PROT_TELNET ? IDC0_PROTTELNET : IDC0_PROTRAW));
374330e2 594 CheckDlgButton (hwnd, IDC0_CLOSEEXIT, cfg.close_on_exit);
9ef49106 595 CheckDlgButton (hwnd, IDC0_CLOSEWARN, cfg.warn_on_close);
374330e2 596 SendDlgItemMessage (hwnd, IDC0_SESSLIST, LB_SETCURSEL,
597 (WPARAM) -1, 0);
598 }
599 if (LOWORD(wParam) == IDC0_SESSLIST) {
600 /*
601 * A double-click on a saved session should
602 * actually start the session, not just load it.
603 * Unless it's Default Settings or some other
604 * host-less set of saved settings.
605 */
1cd246bb 606 if (*cfg.host) {
607 readytogo = TRUE;
608 SetCapture(hwnd);
609 }
374330e2 610 }
611 break;
612 case IDC0_SESSDEL:
613 if (HIWORD(wParam) == BN_CLICKED ||
614 HIWORD(wParam) == BN_DOUBLECLICKED) {
615 int n = SendDlgItemMessage (hwnd, IDC0_SESSLIST,
616 LB_GETCURSEL, 0, 0);
617 if (n == LB_ERR || n == 0) {
618 MessageBeep(0);
619 break;
620 }
621 del_session(sessions[n]);
622 get_sesslist (FALSE);
623 get_sesslist (TRUE);
624 SendDlgItemMessage (hwnd, IDC0_SESSLIST, LB_RESETCONTENT,
625 0, 0);
626 for (i = 0; i < nsessions; i++)
627 SendDlgItemMessage (hwnd, IDC0_SESSLIST, LB_ADDSTRING,
628 0, (LPARAM) (sessions[i]));
629 SendDlgItemMessage (hwnd, IDC0_SESSLIST, LB_SETCURSEL,
630 (WPARAM) -1, 0);
631 }
632 }
633 }
634 return GeneralPanelProc (hwnd, msg, wParam, lParam);
635}
636
637static int CALLBACK KeyboardProc (HWND hwnd, UINT msg,
638 WPARAM wParam, LPARAM lParam) {
639 switch (msg) {
640 case WM_INITDIALOG:
641 CheckRadioButton (hwnd, IDC1_DEL008, IDC1_DEL127,
642 cfg.bksp_is_delete ? IDC1_DEL127 : IDC1_DEL008);
643 CheckRadioButton (hwnd, IDC1_HOMETILDE, IDC1_HOMERXVT,
644 cfg.rxvt_homeend ? IDC1_HOMERXVT : IDC1_HOMETILDE);
645 CheckRadioButton (hwnd, IDC1_FUNCTILDE, IDC1_FUNCLINUX,
646 cfg.linux_funkeys ? IDC1_FUNCLINUX : IDC1_FUNCTILDE);
647 CheckRadioButton (hwnd, IDC1_CURNORMAL, IDC1_CURAPPLIC,
648 cfg.app_cursor ? IDC1_CURAPPLIC : IDC1_CURNORMAL);
c5e9c988 649 CheckRadioButton (hwnd, IDC1_KPNORMAL, IDC1_KPNH,
650 cfg.nethack_keypad ? IDC1_KPNH :
374330e2 651 cfg.app_keypad ? IDC1_KPAPPLIC : IDC1_KPNORMAL);
c5e9c988 652 CheckDlgButton (hwnd, IDC1_ALTF4, cfg.alt_f4);
653 CheckDlgButton (hwnd, IDC1_ALTSPACE, cfg.alt_space);
5bc238bb 654 CheckDlgButton (hwnd, IDC1_LDISCTERM, cfg.ldisc_term);
217dceef 655 CheckDlgButton (hwnd, IDC1_BLINKCUR, cfg.blink_cur);
2a25a1b4 656 CheckDlgButton (hwnd, IDC1_BEEP, cfg.beep);
374330e2 657 break;
658 case WM_COMMAND:
659 if (HIWORD(wParam) == BN_CLICKED ||
660 HIWORD(wParam) == BN_DOUBLECLICKED)
661 switch (LOWORD(wParam)) {
662 case IDC1_DEL008:
663 case IDC1_DEL127:
664 cfg.bksp_is_delete = IsDlgButtonChecked (hwnd, IDC1_DEL127);
665 break;
666 case IDC1_HOMETILDE:
667 case IDC1_HOMERXVT:
668 cfg.rxvt_homeend = IsDlgButtonChecked (hwnd, IDC1_HOMERXVT);
669 break;
670 case IDC1_FUNCTILDE:
671 case IDC1_FUNCLINUX:
672 cfg.linux_funkeys = IsDlgButtonChecked (hwnd, IDC1_FUNCLINUX);
673 break;
674 case IDC1_KPNORMAL:
675 case IDC1_KPAPPLIC:
676 cfg.app_keypad = IsDlgButtonChecked (hwnd, IDC1_KPAPPLIC);
c5e9c988 677 cfg.nethack_keypad = FALSE;
678 break;
679 case IDC1_KPNH:
680 cfg.app_keypad = FALSE;
681 cfg.nethack_keypad = TRUE;
374330e2 682 break;
683 case IDC1_CURNORMAL:
684 case IDC1_CURAPPLIC:
685 cfg.app_cursor = IsDlgButtonChecked (hwnd, IDC1_CURAPPLIC);
686 break;
c5e9c988 687 case IDC1_ALTF4:
688 if (HIWORD(wParam) == BN_CLICKED ||
689 HIWORD(wParam) == BN_DOUBLECLICKED)
690 cfg.alt_f4 = IsDlgButtonChecked (hwnd, IDC1_ALTF4);
691 break;
692 case IDC1_ALTSPACE:
693 if (HIWORD(wParam) == BN_CLICKED ||
694 HIWORD(wParam) == BN_DOUBLECLICKED)
695 cfg.alt_space = IsDlgButtonChecked (hwnd, IDC1_ALTSPACE);
696 break;
5bc238bb 697 case IDC1_LDISCTERM:
698 if (HIWORD(wParam) == BN_CLICKED ||
699 HIWORD(wParam) == BN_DOUBLECLICKED)
700 cfg.ldisc_term = IsDlgButtonChecked (hwnd, IDC1_LDISCTERM);
701 break;
217dceef 702 case IDC1_BLINKCUR:
703 if (HIWORD(wParam) == BN_CLICKED ||
704 HIWORD(wParam) == BN_DOUBLECLICKED)
705 cfg.blink_cur = IsDlgButtonChecked (hwnd, IDC1_BLINKCUR);
2a25a1b4 706 case IDC1_BEEP:
707 if (HIWORD(wParam) == BN_CLICKED ||
708 HIWORD(wParam) == BN_DOUBLECLICKED)
709 cfg.beep = IsDlgButtonChecked (hwnd, IDC1_BEEP);
217dceef 710 break;
374330e2 711 }
712 }
713 return GeneralPanelProc (hwnd, msg, wParam, lParam);
714}
715
716static void fmtfont (char *buf) {
717 sprintf (buf, "Font: %s, ", cfg.font);
718 if (cfg.fontisbold)
719 strcat(buf, "bold, ");
720 if (cfg.fontheight == 0)
721 strcat (buf, "default height");
722 else
723 sprintf (buf+strlen(buf), "%d-%s",
724 (cfg.fontheight < 0 ? -cfg.fontheight : cfg.fontheight),
725 (cfg.fontheight < 0 ? "pixel" : "point"));
726}
727
728static int CALLBACK TerminalProc (HWND hwnd, UINT msg,
729 WPARAM wParam, LPARAM lParam) {
730 CHOOSEFONT cf;
731 LOGFONT lf;
732 char fontstatic[256];
733
734 switch (msg) {
735 case WM_INITDIALOG:
736 CheckDlgButton (hwnd, IDC2_WRAPMODE, cfg.wrap_mode);
737 CheckDlgButton (hwnd, IDC2_WINNAME, cfg.win_name_always);
738 CheckDlgButton (hwnd, IDC2_DECOM, cfg.dec_om);
fef97f43 739 CheckDlgButton (hwnd, IDC2_LFHASCR, cfg.lfhascr);
374330e2 740 SetDlgItemInt (hwnd, IDC2_ROWSEDIT, cfg.height, FALSE);
741 SetDlgItemInt (hwnd, IDC2_COLSEDIT, cfg.width, FALSE);
742 SetDlgItemInt (hwnd, IDC2_SAVEEDIT, cfg.savelines, FALSE);
743 fmtfont (fontstatic);
744 SetDlgItemText (hwnd, IDC2_FONTSTATIC, fontstatic);
745 CheckRadioButton (hwnd, IDC2_VTXWINDOWS, IDC2_VTPOORMAN,
746 cfg.vtmode == VT_XWINDOWS ? IDC2_VTXWINDOWS :
747 cfg.vtmode == VT_OEMANSI ? IDC2_VTOEMANSI :
748 cfg.vtmode == VT_OEMONLY ? IDC2_VTOEMONLY :
749 IDC2_VTPOORMAN);
750 break;
751 case WM_COMMAND:
752 switch (LOWORD(wParam)) {
753 case IDC2_WRAPMODE:
754 if (HIWORD(wParam) == BN_CLICKED ||
755 HIWORD(wParam) == BN_DOUBLECLICKED)
756 cfg.wrap_mode = IsDlgButtonChecked (hwnd, IDC2_WRAPMODE);
757 break;
758 case IDC2_WINNAME:
759 if (HIWORD(wParam) == BN_CLICKED ||
760 HIWORD(wParam) == BN_DOUBLECLICKED)
761 cfg.win_name_always = IsDlgButtonChecked (hwnd, IDC2_WINNAME);
762 break;
763 case IDC2_DECOM:
764 if (HIWORD(wParam) == BN_CLICKED ||
765 HIWORD(wParam) == BN_DOUBLECLICKED)
766 cfg.dec_om = IsDlgButtonChecked (hwnd, IDC2_DECOM);
767 break;
fef97f43 768 case IDC2_LFHASCR:
769 if (HIWORD(wParam) == BN_CLICKED ||
770 HIWORD(wParam) == BN_DOUBLECLICKED)
771 cfg.lfhascr = IsDlgButtonChecked (hwnd, IDC2_LFHASCR);
772 break;
374330e2 773 case IDC2_ROWSEDIT:
774 if (HIWORD(wParam) == EN_CHANGE)
775 MyGetDlgItemInt (hwnd, IDC2_ROWSEDIT, &cfg.height);
776 break;
777 case IDC2_COLSEDIT:
778 if (HIWORD(wParam) == EN_CHANGE)
779 MyGetDlgItemInt (hwnd, IDC2_COLSEDIT, &cfg.width);
780 break;
781 case IDC2_SAVEEDIT:
782 if (HIWORD(wParam) == EN_CHANGE)
783 MyGetDlgItemInt (hwnd, IDC2_SAVEEDIT, &cfg.savelines);
784 break;
785 case IDC2_CHOOSEFONT:
786 lf.lfHeight = cfg.fontheight;
787 lf.lfWidth = lf.lfEscapement = lf.lfOrientation = 0;
788 lf.lfItalic = lf.lfUnderline = lf.lfStrikeOut = 0;
789 lf.lfWeight = (cfg.fontisbold ? FW_BOLD : 0);
14963b8f 790 lf.lfCharSet = cfg.fontcharset;
374330e2 791 lf.lfOutPrecision = OUT_DEFAULT_PRECIS;
792 lf.lfClipPrecision = CLIP_DEFAULT_PRECIS;
793 lf.lfQuality = DEFAULT_QUALITY;
794 lf.lfPitchAndFamily = FIXED_PITCH | FF_DONTCARE;
795 strncpy (lf.lfFaceName, cfg.font, sizeof(lf.lfFaceName)-1);
796 lf.lfFaceName[sizeof(lf.lfFaceName)-1] = '\0';
797
798 cf.lStructSize = sizeof(cf);
799 cf.hwndOwner = hwnd;
800 cf.lpLogFont = &lf;
801 cf.Flags = CF_FIXEDPITCHONLY | CF_FORCEFONTEXIST |
802 CF_INITTOLOGFONTSTRUCT | CF_SCREENFONTS;
803
804 if (ChooseFont (&cf)) {
805 strncpy (cfg.font, lf.lfFaceName, sizeof(cfg.font)-1);
806 cfg.font[sizeof(cfg.font)-1] = '\0';
807 cfg.fontisbold = (lf.lfWeight == FW_BOLD);
14963b8f 808 cfg.fontcharset = lf.lfCharSet;
374330e2 809 cfg.fontheight = lf.lfHeight;
810 fmtfont (fontstatic);
811 SetDlgItemText (hwnd, IDC2_FONTSTATIC, fontstatic);
812 }
813 break;
814 case IDC2_VTXWINDOWS:
815 case IDC2_VTOEMANSI:
816 case IDC2_VTOEMONLY:
817 case IDC2_VTPOORMAN:
818 cfg.vtmode =
819 (IsDlgButtonChecked (hwnd, IDC2_VTXWINDOWS) ? VT_XWINDOWS :
820 IsDlgButtonChecked (hwnd, IDC2_VTOEMANSI) ? VT_OEMANSI :
821 IsDlgButtonChecked (hwnd, IDC2_VTOEMONLY) ? VT_OEMONLY :
822 VT_POORMAN);
823 break;
824 }
825 break;
826 }
827 return GeneralPanelProc (hwnd, msg, wParam, lParam);
828}
829
830static int CALLBACK TelnetProc (HWND hwnd, UINT msg,
831 WPARAM wParam, LPARAM lParam) {
832 int i;
833
834 switch (msg) {
835 case WM_INITDIALOG:
836 SetDlgItemText (hwnd, IDC3_TTEDIT, cfg.termtype);
837 SetDlgItemText (hwnd, IDC3_TSEDIT, cfg.termspeed);
838 SetDlgItemText (hwnd, IDC3_LOGEDIT, cfg.username);
839 {
37508af4 840 char *p = cfg.environmt;
374330e2 841 while (*p) {
842 SendDlgItemMessage (hwnd, IDC3_ENVLIST, LB_ADDSTRING, 0,
843 (LPARAM) p);
844 p += strlen(p)+1;
845 }
846 }
847 CheckRadioButton (hwnd, IDC3_EMBSD, IDC3_EMRFC,
848 cfg.rfc_environ ? IDC3_EMRFC : IDC3_EMBSD);
849 break;
850 case WM_COMMAND:
851 switch (LOWORD(wParam)) {
852 case IDC3_TTEDIT:
853 if (HIWORD(wParam) == EN_CHANGE)
854 GetDlgItemText (hwnd, IDC3_TTEDIT, cfg.termtype,
855 sizeof(cfg.termtype)-1);
856 break;
857 case IDC3_TSEDIT:
858 if (HIWORD(wParam) == EN_CHANGE)
859 GetDlgItemText (hwnd, IDC3_TSEDIT, cfg.termspeed,
860 sizeof(cfg.termspeed)-1);
861 break;
862 case IDC3_LOGEDIT:
863 if (HIWORD(wParam) == EN_CHANGE)
864 GetDlgItemText (hwnd, IDC3_LOGEDIT, cfg.username,
865 sizeof(cfg.username)-1);
866 break;
867 case IDC3_EMBSD:
868 case IDC3_EMRFC:
869 cfg.rfc_environ = IsDlgButtonChecked (hwnd, IDC3_EMRFC);
870 break;
871 case IDC3_ENVADD:
872 if (HIWORD(wParam) == BN_CLICKED ||
873 HIWORD(wParam) == BN_DOUBLECLICKED) {
37508af4 874 char str[sizeof(cfg.environmt)];
374330e2 875 char *p;
876 GetDlgItemText (hwnd, IDC3_VAREDIT, str, sizeof(str)-1);
877 if (!*str) {
878 MessageBeep(0);
879 break;
880 }
881 p = str + strlen(str);
882 *p++ = '\t';
883 GetDlgItemText (hwnd, IDC3_VALEDIT, p, sizeof(str)-1-(p-str));
884 if (!*p) {
885 MessageBeep(0);
886 break;
887 }
37508af4 888 p = cfg.environmt;
374330e2 889 while (*p) {
890 while (*p) p++;
891 p++;
892 }
37508af4 893 if ((p-cfg.environmt) + strlen(str) + 2 < sizeof(cfg.environmt)) {
374330e2 894 strcpy (p, str);
895 p[strlen(str)+1] = '\0';
896 SendDlgItemMessage (hwnd, IDC3_ENVLIST, LB_ADDSTRING,
897 0, (LPARAM)str);
898 SetDlgItemText (hwnd, IDC3_VAREDIT, "");
899 SetDlgItemText (hwnd, IDC3_VALEDIT, "");
900 } else {
901 MessageBox(hwnd, "Environment too big", "PuTTY Error",
902 MB_OK | MB_ICONERROR);
903 }
904 }
905 break;
906 case IDC3_ENVREMOVE:
907 if (HIWORD(wParam) != BN_CLICKED &&
908 HIWORD(wParam) != BN_DOUBLECLICKED)
909 break;
910 i = SendDlgItemMessage (hwnd, IDC3_ENVLIST, LB_GETCURSEL, 0, 0);
911 if (i == LB_ERR)
912 MessageBeep (0);
913 else {
914 char *p, *q;
915
916 SendDlgItemMessage (hwnd, IDC3_ENVLIST, LB_DELETESTRING,
917 i, 0);
37508af4 918 p = cfg.environmt;
374330e2 919 while (i > 0) {
920 if (!*p)
921 goto disaster;
922 while (*p) p++;
923 p++;
924 i--;
925 }
926 q = p;
927 if (!*p)
928 goto disaster;
929 while (*p) p++;
930 p++;
931 while (*p) {
932 while (*p)
933 *q++ = *p++;
934 *q++ = *p++;
935 }
936 *q = '\0';
937 disaster:;
938 }
939 break;
940 }
941 break;
942 }
943 return GeneralPanelProc (hwnd, msg, wParam, lParam);
944}
945
946static int CALLBACK SshProc (HWND hwnd, UINT msg,
947 WPARAM wParam, LPARAM lParam) {
948 switch (msg) {
949 case WM_INITDIALOG:
950 SetDlgItemText (hwnd, IDC3_TTEDIT, cfg.termtype);
951 SetDlgItemText (hwnd, IDC3_LOGEDIT, cfg.username);
fef97f43 952 CheckDlgButton (hwnd, IDC3_NOPTY, cfg.nopty);
9697bfd2 953 CheckRadioButton (hwnd, IDC3_CIPHER3DES, IDC3_CIPHERDES,
bea1ef5f 954 cfg.cipher == CIPHER_BLOWFISH ? IDC3_CIPHERBLOWF :
9697bfd2 955 cfg.cipher == CIPHER_DES ? IDC3_CIPHERDES :
956
bea1ef5f 957 IDC3_CIPHER3DES);
ccbfb941 958 CheckDlgButton (hwnd, IDC3_AUTHTIS, cfg.try_tis_auth);
374330e2 959 break;
960 case WM_COMMAND:
961 switch (LOWORD(wParam)) {
962 case IDC3_TTEDIT:
963 if (HIWORD(wParam) == EN_CHANGE)
964 GetDlgItemText (hwnd, IDC3_TTEDIT, cfg.termtype,
965 sizeof(cfg.termtype)-1);
966 break;
967 case IDC3_LOGEDIT:
968 if (HIWORD(wParam) == EN_CHANGE)
969 GetDlgItemText (hwnd, IDC3_LOGEDIT, cfg.username,
970 sizeof(cfg.username)-1);
971 break;
fef97f43 972 case IDC3_NOPTY:
973 if (HIWORD(wParam) == BN_CLICKED ||
974 HIWORD(wParam) == BN_DOUBLECLICKED)
975 cfg.nopty = IsDlgButtonChecked (hwnd, IDC3_NOPTY);
976 break;
bea1ef5f 977 case IDC3_CIPHER3DES:
978 case IDC3_CIPHERBLOWF:
9697bfd2 979 case IDC3_CIPHERDES:
bea1ef5f 980 if (HIWORD(wParam) == BN_CLICKED ||
981 HIWORD(wParam) == BN_DOUBLECLICKED) {
982 if (IsDlgButtonChecked (hwnd, IDC3_CIPHER3DES))
983 cfg.cipher = CIPHER_3DES;
984 else if (IsDlgButtonChecked (hwnd, IDC3_CIPHERBLOWF))
985 cfg.cipher = CIPHER_BLOWFISH;
9697bfd2 986 else if (IsDlgButtonChecked (hwnd, IDC3_CIPHERDES))
987 cfg.cipher = CIPHER_DES;
bea1ef5f 988 }
989 break;
ccbfb941 990 case IDC3_AUTHTIS:
991 if (HIWORD(wParam) == BN_CLICKED ||
992 HIWORD(wParam) == BN_DOUBLECLICKED)
993 cfg.try_tis_auth = IsDlgButtonChecked (hwnd, IDC3_AUTHTIS);
994 break;
374330e2 995 }
996 break;
997 }
998 return GeneralPanelProc (hwnd, msg, wParam, lParam);
999}
1000
1001static int CALLBACK SelectionProc (HWND hwnd, UINT msg,
1002 WPARAM wParam, LPARAM lParam) {
1003 int i;
1004
1005 switch (msg) {
1006 case WM_INITDIALOG:
1007 CheckRadioButton (hwnd, IDC4_MBWINDOWS, IDC4_MBXTERM,
1008 cfg.mouse_is_xterm ? IDC4_MBXTERM : IDC4_MBWINDOWS);
1009 {
1010 static int tabs[4] = {25, 61, 96, 128};
1011 SendDlgItemMessage (hwnd, IDC4_CCLIST, LB_SETTABSTOPS, 4,
1012 (LPARAM) tabs);
1013 }
1014 for (i=0; i<256; i++) {
1015 char str[100];
1016 sprintf(str, "%d\t(0x%02X)\t%c\t%d", i, i,
1017 (i>=0x21 && i != 0x7F) ? i : ' ',
1018 cfg.wordness[i]);
1019 SendDlgItemMessage (hwnd, IDC4_CCLIST, LB_ADDSTRING, 0,
1020 (LPARAM) str);
1021 }
1022 break;
1023 case WM_COMMAND:
1024 switch (LOWORD(wParam)) {
1025 case IDC4_MBWINDOWS:
1026 case IDC4_MBXTERM:
1027 cfg.mouse_is_xterm = IsDlgButtonChecked (hwnd, IDC4_MBXTERM);
1028 break;
1029 case IDC4_CCSET:
1030 {
1031 BOOL ok;
1032 int i;
1033 int n = GetDlgItemInt (hwnd, IDC4_CCEDIT, &ok, FALSE);
1034
1035 if (!ok)
1036 MessageBeep (0);
1037 else {
1038 for (i=0; i<256; i++)
1039 if (SendDlgItemMessage (hwnd, IDC4_CCLIST, LB_GETSEL,
1040 i, 0)) {
1041 char str[100];
1042 cfg.wordness[i] = n;
1043 SendDlgItemMessage (hwnd, IDC4_CCLIST,
1044 LB_DELETESTRING, i, 0);
1045 sprintf(str, "%d\t(0x%02X)\t%c\t%d", i, i,
1046 (i>=0x21 && i != 0x7F) ? i : ' ',
1047 cfg.wordness[i]);
1048 SendDlgItemMessage (hwnd, IDC4_CCLIST,
1049 LB_INSERTSTRING, i,
1050 (LPARAM)str);
1051 }
1052 }
1053 }
1054 break;
1055 }
1056 break;
1057 }
1058 return GeneralPanelProc (hwnd, msg, wParam, lParam);
1059}
1060
1061static int CALLBACK ColourProc (HWND hwnd, UINT msg,
1062 WPARAM wParam, LPARAM lParam) {
1063 static const char *const colours[] = {
1064 "Default Foreground", "Default Bold Foreground",
1065 "Default Background", "Default Bold Background",
1066 "Cursor Text", "Cursor Colour",
1067 "ANSI Black", "ANSI Black Bold",
1068 "ANSI Red", "ANSI Red Bold",
1069 "ANSI Green", "ANSI Green Bold",
1070 "ANSI Yellow", "ANSI Yellow Bold",
1071 "ANSI Blue", "ANSI Blue Bold",
1072 "ANSI Magenta", "ANSI Magenta Bold",
1073 "ANSI Cyan", "ANSI Cyan Bold",
1074 "ANSI White", "ANSI White Bold"
1075 };
1076 static const int permanent[] = {
1077 TRUE, FALSE, TRUE, FALSE, TRUE, TRUE,
1078 TRUE, FALSE, TRUE, FALSE, TRUE, FALSE, TRUE, FALSE,
1079 TRUE, FALSE, TRUE, FALSE, TRUE, FALSE, TRUE, FALSE
1080 };
1081 switch (msg) {
1082 case WM_INITDIALOG:
1083 CheckDlgButton (hwnd, IDC5_BOLDCOLOUR, cfg.bold_colour);
1084 CheckDlgButton (hwnd, IDC5_PALETTE, cfg.try_palette);
1085 {
1086 int i;
1087 for (i=0; i<22; i++)
1088 if (cfg.bold_colour || permanent[i])
1089 SendDlgItemMessage (hwnd, IDC5_LIST, LB_ADDSTRING, 0,
1090 (LPARAM) colours[i]);
1091 }
1092 SendDlgItemMessage (hwnd, IDC5_LIST, LB_SETCURSEL, 0, 0);
1093 SetDlgItemInt (hwnd, IDC5_RVALUE, cfg.colours[0][0], FALSE);
1094 SetDlgItemInt (hwnd, IDC5_GVALUE, cfg.colours[0][1], FALSE);
1095 SetDlgItemInt (hwnd, IDC5_BVALUE, cfg.colours[0][2], FALSE);
1096 break;
1097 case WM_COMMAND:
1098 switch (LOWORD(wParam)) {
1099 case IDC5_BOLDCOLOUR:
1100 if (HIWORD(wParam) == BN_CLICKED ||
1101 HIWORD(wParam) == BN_DOUBLECLICKED) {
1102 int n, i;
1103 cfg.bold_colour = IsDlgButtonChecked (hwnd, IDC5_BOLDCOLOUR);
1104 n = SendDlgItemMessage (hwnd, IDC5_LIST, LB_GETCOUNT, 0, 0);
1105 if (cfg.bold_colour && n!=22) {
1106 for (i=0; i<22; i++)
1107 if (!permanent[i])
1108 SendDlgItemMessage (hwnd, IDC5_LIST,
1109 LB_INSERTSTRING, i,
1110 (LPARAM) colours[i]);
1111 } else if (!cfg.bold_colour && n!=12) {
1112 for (i=22; i-- ;)
1113 if (!permanent[i])
1114 SendDlgItemMessage (hwnd, IDC5_LIST,
1115 LB_DELETESTRING, i, 0);
1116 }
1117 }
1118 break;
1119 case IDC5_PALETTE:
1120 if (HIWORD(wParam) == BN_CLICKED ||
1121 HIWORD(wParam) == BN_DOUBLECLICKED)
1122 cfg.try_palette = IsDlgButtonChecked (hwnd, IDC5_PALETTE);
1123 break;
1124 case IDC5_LIST:
1125 if (HIWORD(wParam) == LBN_DBLCLK ||
1126 HIWORD(wParam) == LBN_SELCHANGE) {
1127 int i = SendDlgItemMessage (hwnd, IDC5_LIST, LB_GETCURSEL,
1128 0, 0);
1129 if (!cfg.bold_colour)
1130 i = (i < 3 ? i*2 : i == 3 ? 5 : i*2-2);
1131 SetDlgItemInt (hwnd, IDC5_RVALUE, cfg.colours[i][0], FALSE);
1132 SetDlgItemInt (hwnd, IDC5_GVALUE, cfg.colours[i][1], FALSE);
1133 SetDlgItemInt (hwnd, IDC5_BVALUE, cfg.colours[i][2], FALSE);
1134 }
1135 break;
1136 case IDC5_CHANGE:
1137 if (HIWORD(wParam) == BN_CLICKED ||
1138 HIWORD(wParam) == BN_DOUBLECLICKED) {
1139 static CHOOSECOLOR cc;
1140 static DWORD custom[16] = {0}; /* zero initialisers */
1141 int i = SendDlgItemMessage (hwnd, IDC5_LIST, LB_GETCURSEL,
1142 0, 0);
1143 if (!cfg.bold_colour)
1144 i = (i < 3 ? i*2 : i == 3 ? 5 : i*2-2);
1145 cc.lStructSize = sizeof(cc);
1146 cc.hwndOwner = hwnd;
1d470ad2 1147 cc.hInstance = (HWND)hinst;
374330e2 1148 cc.lpCustColors = custom;
1149 cc.rgbResult = RGB (cfg.colours[i][0], cfg.colours[i][1],
1150 cfg.colours[i][2]);
1151 cc.Flags = CC_FULLOPEN | CC_RGBINIT;
1152 if (ChooseColor(&cc)) {
1153 cfg.colours[i][0] =
1154 (unsigned char) (cc.rgbResult & 0xFF);
1155 cfg.colours[i][1] =
1156 (unsigned char) (cc.rgbResult >> 8) & 0xFF;
1157 cfg.colours[i][2] =
1158 (unsigned char) (cc.rgbResult >> 16) & 0xFF;
1159 SetDlgItemInt (hwnd, IDC5_RVALUE, cfg.colours[i][0],
1160 FALSE);
1161 SetDlgItemInt (hwnd, IDC5_GVALUE, cfg.colours[i][1],
1162 FALSE);
1163 SetDlgItemInt (hwnd, IDC5_BVALUE, cfg.colours[i][2],
1164 FALSE);
1165 }
1166 }
1167 break;
1168 }
1169 break;
1170 }
1171 return GeneralPanelProc (hwnd, msg, wParam, lParam);
1172}
1173
14963b8f 1174static int CALLBACK LanguageProc (HWND hwnd, UINT msg,
1175 WPARAM wParam, LPARAM lParam) {
1176 switch (msg) {
1177 case WM_INITDIALOG:
d3d16feb 1178 CheckRadioButton (hwnd, IDC6_NOXLAT, IDC6_88592WIN1250,
1179 cfg.xlat_88592w1250 ? IDC6_88592WIN1250 :
1180 cfg.xlat_enablekoiwin ? IDC6_KOI8WIN1251 :
1181 IDC6_NOXLAT);
14963b8f 1182 CheckDlgButton (hwnd, IDC6_CAPSLOCKCYR, cfg.xlat_capslockcyr);
1183 case WM_COMMAND:
1184 switch (LOWORD(wParam)) {
d3d16feb 1185 case IDC6_NOXLAT:
1186 case IDC6_KOI8WIN1251:
1187 case IDC6_88592WIN1250:
1188 cfg.xlat_enablekoiwin =
1189 IsDlgButtonChecked (hwnd, IDC6_KOI8WIN1251);
1190 cfg.xlat_88592w1250 =
1191 IsDlgButtonChecked (hwnd, IDC6_88592WIN1250);
14963b8f 1192 break;
1193 case IDC6_CAPSLOCKCYR:
1194 if (HIWORD(wParam) == BN_CLICKED ||
1195 HIWORD(wParam) == BN_DOUBLECLICKED) {
1196 cfg.xlat_capslockcyr =
1197 IsDlgButtonChecked (hwnd, IDC6_CAPSLOCKCYR);
1198 }
1199 break;
1200 }
1201 }
1202 return GeneralPanelProc (hwnd, msg, wParam, lParam);
1203}
1204
374330e2 1205static DLGPROC panelproc[NPANELS] = {
1206 ConnectionProc, KeyboardProc, TerminalProc,
14963b8f 1207 TelnetProc, SshProc, SelectionProc, ColourProc, LanguageProc
374330e2 1208};
1209static char *panelids[NPANELS] = {
1210 MAKEINTRESOURCE(IDD_PANEL0),
1211 MAKEINTRESOURCE(IDD_PANEL1),
1212 MAKEINTRESOURCE(IDD_PANEL2),
1213 MAKEINTRESOURCE(IDD_PANEL3),
1214 MAKEINTRESOURCE(IDD_PANEL35),
1215 MAKEINTRESOURCE(IDD_PANEL4),
14963b8f 1216 MAKEINTRESOURCE(IDD_PANEL5),
1217 MAKEINTRESOURCE(IDD_PANEL6)
374330e2 1218};
14963b8f 1219
374330e2 1220static char *names[NPANELS] = {
14963b8f 1221 "Connection", "Keyboard", "Terminal", "Telnet",
1222 "SSH", "Selection", "Colours", "Language"
374330e2 1223};
1224
14963b8f 1225static int mainp[MAIN_NPANELS] = { 0, 1, 2, 3, 4, 5, 6, 7};
1226static int reconfp[RECONF_NPANELS] = { 1, 2, 5, 6, 7};
374330e2 1227
1228static int GenericMainDlgProc (HWND hwnd, UINT msg,
1229 WPARAM wParam, LPARAM lParam,
1230 int npanels, int *panelnums, HWND *page) {
1231 HWND hw;
1232
1233 switch (msg) {
1234 case WM_INITDIALOG:
1235 { /* centre the window */
1236 RECT rs, rd;
1237
1238 hw = GetDesktopWindow();
1239 if (GetWindowRect (hw, &rs) && GetWindowRect (hwnd, &rd))
1240 MoveWindow (hwnd, (rs.right + rs.left + rd.left - rd.right)/2,
1241 (rs.bottom + rs.top + rd.top - rd.bottom)/2,
1242 rd.right-rd.left, rd.bottom-rd.top, TRUE);
1243 }
1244 *page = NULL;
1245 { /* initialise the tab control */
1246 TC_ITEMHEADER tab;
1247 int i;
1248
1249 hw = GetDlgItem (hwnd, IDC_TAB);
1250 for (i=0; i<npanels; i++) {
1251 tab.mask = TCIF_TEXT;
1252 tab.pszText = names[panelnums[i]];
1253 TabCtrl_InsertItem (hw, i, &tab);
1254 }
1255/* *page = CreateDialogIndirect (hinst, panels[panelnums[0]].temp,
1256 hwnd, panelproc[panelnums[0]]);*/
1257 *page = CreateDialog (hinst, panelids[panelnums[0]],
1258 hwnd, panelproc[panelnums[0]]);
1259 SetWindowLong (*page, GWL_EXSTYLE,
1260 GetWindowLong (*page, GWL_EXSTYLE) |
1261 WS_EX_CONTROLPARENT);
1262 }
1263 SetFocus (*page);
1264 return 0;
1265 case WM_NOTIFY:
1266 if (LOWORD(wParam) == IDC_TAB &&
1267 ((LPNMHDR)lParam)->code == TCN_SELCHANGE) {
1268 int i = TabCtrl_GetCurSel(((LPNMHDR)lParam)->hwndFrom);
1269 if (*page)
1270 DestroyWindow (*page);
1271/* *page = CreateDialogIndirect (hinst, panels[panelnums[i]].temp,
1272 hwnd, panelproc[panelnums[i]]);*/
1273 *page = CreateDialog (hinst, panelids[panelnums[i]],
1274 hwnd, panelproc[panelnums[i]]);
1275 SetWindowLong (*page, GWL_EXSTYLE,
1276 GetWindowLong (*page, GWL_EXSTYLE) |
1277 WS_EX_CONTROLPARENT);
1278 SetFocus (((LPNMHDR)lParam)->hwndFrom); /* ensure focus stays */
1279 return 0;
1280 }
1281 break;
1282/* case WM_CTLCOLORDLG: */
1283/* return (int) GetStockObject (LTGRAY_BRUSH); */
1284 case WM_COMMAND:
1285 switch (LOWORD(wParam)) {
1286 case IDOK:
1287 if (*cfg.host)
1288 EndDialog (hwnd, 1);
1289 else
1290 MessageBeep (0);
1291 return 0;
1292 case IDCANCEL:
1293 EndDialog (hwnd, 0);
1294 return 0;
1295 }
1296 return 0;
1297 case WM_CLOSE:
1298 EndDialog (hwnd, 0);
1299 return 0;
1300 }
1301 return 0;
1302}
1303
1304static int CALLBACK MainDlgProc (HWND hwnd, UINT msg,
1305 WPARAM wParam, LPARAM lParam) {
1306#if 0
1307 HWND hw;
1308 int i;
1309#endif
1310 static HWND page = NULL;
1311
1312 if (msg == WM_COMMAND && LOWORD(wParam) == IDOK) {
1313#if 0
1314 /*
1315 * If the Connection panel is active and the Session List
1316 * box is selected, we treat a press of Open to have an
1317 * implicit press of Load preceding it.
1318 */
1319 hw = GetDlgItem (hwnd, IDC_TAB);
1320 i = TabCtrl_GetCurSel(hw);
1321 if (panelproc[mainp[i]] == ConnectionProc &&
1322 page && implicit_load_ok) {
1323 SendMessage (page, WM_COMMAND,
1324 MAKELONG(IDC0_SESSLOAD, BN_CLICKED), 0);
1325 }
1326#endif
1327 }
1328 if (msg == WM_COMMAND && LOWORD(wParam) == IDC_ABOUT) {
1329 EnableWindow(hwnd, 0);
1330 DialogBox(hinst, MAKEINTRESOURCE(IDD_ABOUTBOX),
1331 GetParent(hwnd), AboutProc);
1332 EnableWindow(hwnd, 1);
1333 }
1334 return GenericMainDlgProc (hwnd, msg, wParam, lParam,
1335 MAIN_NPANELS, mainp, &page);
1336}
1337
1338static int CALLBACK ReconfDlgProc (HWND hwnd, UINT msg,
1339 WPARAM wParam, LPARAM lParam) {
1340 static HWND page;
1341 return GenericMainDlgProc (hwnd, msg, wParam, lParam,
1342 RECONF_NPANELS, reconfp, &page);
1343}
1344
0a4aa984 1345void get_sesslist(int allocate) {
374330e2 1346 static char *buffer;
1347 int buflen, bufsize, i, ret;
1348 char otherbuf[2048];
1349 char *p;
1350 HKEY subkey1;
1351
1352 if (allocate) {
1353 if (RegCreateKey(HKEY_CURRENT_USER,
1354 puttystr, &subkey1) != ERROR_SUCCESS)
1355 return;
1356
1357 buflen = bufsize = 0;
1358 buffer = NULL;
1359 i = 0;
1360 do {
1361 ret = RegEnumKey(subkey1, i++, otherbuf, sizeof(otherbuf));
1362 if (ret == ERROR_SUCCESS) {
1363 bufsize = buflen + 2048;
1364 buffer = srealloc(buffer, bufsize);
1365 unmungestr(otherbuf, buffer+buflen);
1366 buflen += strlen(buffer+buflen)+1;
1367 }
1368 } while (ret == ERROR_SUCCESS);
1369 buffer = srealloc(buffer, buflen+1);
1370 buffer[buflen] = '\0';
1371
1372 p = buffer;
1373 nsessions = 1; /* "Default Settings" counts as one */
1374 while (*p) {
1375 if (strcmp(p, "Default Settings"))
1376 nsessions++;
1377 while (*p) p++;
1378 p++;
1379 }
1380
1381 sessions = smalloc(nsessions * sizeof(char *));
1382 sessions[0] = "Default Settings";
1383 p = buffer;
1384 i = 1;
1385 while (*p) {
1386 if (strcmp(p, "Default Settings"))
1387 sessions[i++] = p;
1388 while (*p) p++;
1389 p++;
1390 }
1391 } else {
1392 sfree (buffer);
1393 sfree (sessions);
1394 }
1395}
1396
1397int do_config (void) {
1398 int ret;
1399
1400 get_sesslist(TRUE);
1401 ret = DialogBox (hinst, MAKEINTRESOURCE(IDD_MAINBOX), NULL, MainDlgProc);
1402 get_sesslist(FALSE);
1403
1404 return ret;
1405}
1406
1407int do_reconfig (HWND hwnd) {
1408 Config backup_cfg;
1409 int ret;
1410
1411 backup_cfg = cfg; /* structure copy */
1412 ret = DialogBox (hinst, MAKEINTRESOURCE(IDD_RECONF), hwnd, ReconfDlgProc);
1413 if (!ret)
1414 cfg = backup_cfg; /* structure copy */
1415 return ret;
1416}
1417
1418void do_defaults (char *session) {
1419 if (session)
1420 load_settings (session, TRUE);
1421 else
1422 load_settings ("Default Settings", FALSE);
1423}
1424
c5e9c988 1425void logevent (char *string) {
1426 if (nevents >= negsize) {
374330e2 1427 negsize += 64;
c5e9c988 1428 events = srealloc (events, negsize * sizeof(*events));
374330e2 1429 }
c5e9c988 1430 events[nevents] = smalloc(1+strlen(string));
1431 strcpy (events[nevents], string);
1432 nevents++;
374330e2 1433 if (logbox)
1434 SendDlgItemMessage (logbox, IDN_LIST, LB_ADDSTRING,
1435 0, (LPARAM)string);
1436}
1437
c5e9c988 1438void showeventlog (HWND hwnd) {
374330e2 1439 if (!logbox) {
1440 logbox = CreateDialog (hinst, MAKEINTRESOURCE(IDD_LOGBOX),
1441 hwnd, LogProc);
1442 ShowWindow (logbox, SW_SHOWNORMAL);
1443 }
1444}
1445
1446void showabout (HWND hwnd) {
1447 if (!abtbox) {
1448 abtbox = CreateDialog (hinst, MAKEINTRESOURCE(IDD_ABOUTBOX),
1449 hwnd, AboutProc);
1450 ShowWindow (abtbox, SW_SHOWNORMAL);
1451 }
1452}
1453
89ee5268 1454void verify_ssh_host_key(char *host, char *keystr) {
1455 char *otherstr, *mungedhost;
374330e2 1456 int len;
1457 HKEY rkey;
1458
89ee5268 1459 len = 1 + strlen(keystr);
374330e2 1460
1461 /*
1462 * Now read a saved key in from the registry and see what it
1463 * says.
1464 */
1465 otherstr = malloc(len);
1466 mungedhost = malloc(3*strlen(host)+1);
1467 if (!otherstr || !mungedhost)
1468 fatalbox("Out of memory");
1469
1470 mungestr(host, mungedhost);
1471
1472 if (RegCreateKey(HKEY_CURRENT_USER, PUTTY_REG_POS "\\SshHostKeys",
1473 &rkey) != ERROR_SUCCESS) {
1474 if (MessageBox(NULL, "PuTTY was unable to open the host key cache\n"
1475 "in the registry. There is thus no way to tell\n"
1476 "if the remote host is what you think it is.\n"
1477 "Connect anyway?", "PuTTY Problem",
1478 MB_ICONWARNING | MB_YESNO) == IDNO)
1479 exit(0);
1480 } else {
1481 DWORD readlen = len;
1482 DWORD type;
1483 int ret;
1484
1485 ret = RegQueryValueEx(rkey, mungedhost, NULL,
1486 &type, otherstr, &readlen);
1487
1488 if (ret == ERROR_MORE_DATA ||
1489 (ret == ERROR_SUCCESS && type == REG_SZ &&
1490 strcmp(otherstr, keystr))) {
1491 if (MessageBox(NULL,
1492 "This host's host key is different from the\n"
1493 "one cached in the registry! Someone may be\n"
1494 "impersonating this host for malicious reasons;\n"
1495 "alternatively, the host key may have changed\n"
1496 "due to sloppy system administration.\n"
1497 "Replace key in registry and connect?",
1498 "PuTTY: Security Warning",
1499 MB_ICONWARNING | MB_YESNO) == IDNO)
1500 exit(0);
1501 RegSetValueEx(rkey, mungedhost, 0, REG_SZ, keystr,
1502 strlen(keystr)+1);
1503 } else if (ret != ERROR_SUCCESS || type != REG_SZ) {
1504 if (MessageBox(NULL,
1505 "This host's host key is not cached in the\n"
1506 "registry. Do you want to add it to the cache\n"
1507 "and carry on connecting?",
1508 "PuTTY: New Host",
1509 MB_ICONWARNING | MB_YESNO) == IDNO)
1510 exit(0);
1511 RegSetValueEx(rkey, mungedhost, 0, REG_SZ, keystr,
1512 strlen(keystr)+1);
1513 }
1514
1515 RegCloseKey(rkey);
1516 }
1517}