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