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