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