Saved-session name box now persists over panel switches
[sgt/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 return 0;
482 }
483 return 0;
484 case WM_CLOSE:
485 abtbox = NULL;
486 DestroyWindow (hwnd);
487 return 0;
488 }
489 return 0;
490 }
491
492 static int GeneralPanelProc (HWND hwnd, UINT msg,
493 WPARAM wParam, LPARAM lParam) {
494 switch (msg) {
495 case WM_INITDIALOG:
496 SetWindowPos (hwnd, HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);
497 return 1;
498 /* case WM_CTLCOLORDLG: */
499 /* return (int) GetStockObject (LTGRAY_BRUSH); */
500 /* case WM_CTLCOLORSTATIC: */
501 /* case WM_CTLCOLORBTN: */
502 /* SetBkColor ((HDC)wParam, RGB(192,192,192)); */
503 /* return (int) GetStockObject (LTGRAY_BRUSH); */
504 case WM_CLOSE:
505 DestroyWindow (hwnd);
506 return 1;
507 }
508 return 0;
509 }
510
511 static char savedsession[2048];
512
513 static int CALLBACK ConnectionProc (HWND hwnd, UINT msg,
514 WPARAM wParam, LPARAM lParam) {
515 int i;
516
517 switch (msg) {
518 case WM_INITDIALOG:
519 SetDlgItemText (hwnd, IDC0_HOST, cfg.host);
520 SetDlgItemText (hwnd, IDC0_SESSEDIT, savedsession);
521 SetDlgItemInt (hwnd, IDC0_PORT, cfg.port, FALSE);
522 for (i = 0; i < nsessions; i++)
523 SendDlgItemMessage (hwnd, IDC0_SESSLIST, LB_ADDSTRING,
524 0, (LPARAM) (sessions[i]));
525 CheckRadioButton (hwnd, IDC0_PROTRAW, IDC0_PROTSSH,
526 cfg.protocol==PROT_SSH ? IDC0_PROTSSH :
527 cfg.protocol==PROT_TELNET ? IDC0_PROTTELNET : IDC0_PROTRAW );
528 CheckDlgButton (hwnd, IDC0_CLOSEEXIT, cfg.close_on_exit);
529 CheckDlgButton (hwnd, IDC0_CLOSEWARN, cfg.warn_on_close);
530 break;
531 case WM_LBUTTONUP:
532 /*
533 * Button release should trigger WM_OK if there was a
534 * previous double click on the session list.
535 */
536 ReleaseCapture();
537 if (readytogo)
538 SendMessage (GetParent(hwnd), WM_COMMAND, IDOK, 0);
539 break;
540 case WM_COMMAND:
541 switch (LOWORD(wParam)) {
542 case IDC0_PROTTELNET:
543 case IDC0_PROTSSH:
544 case IDC0_PROTRAW:
545 if (HIWORD(wParam) == BN_CLICKED ||
546 HIWORD(wParam) == BN_DOUBLECLICKED) {
547 int i = IsDlgButtonChecked (hwnd, IDC0_PROTSSH);
548 int j = IsDlgButtonChecked (hwnd, IDC0_PROTTELNET);
549 cfg.protocol = i ? PROT_SSH : j ? PROT_TELNET : PROT_RAW ;
550 if ((cfg.protocol == PROT_SSH && cfg.port == 23) ||
551 (cfg.protocol == PROT_TELNET && cfg.port == 22)) {
552 cfg.port = i ? 22 : 23;
553 SetDlgItemInt (hwnd, IDC0_PORT, cfg.port, FALSE);
554 }
555 }
556 break;
557 case IDC0_HOST:
558 if (HIWORD(wParam) == EN_CHANGE)
559 GetDlgItemText (hwnd, IDC0_HOST, cfg.host,
560 sizeof(cfg.host)-1);
561 break;
562 case IDC0_PORT:
563 if (HIWORD(wParam) == EN_CHANGE)
564 MyGetDlgItemInt (hwnd, IDC0_PORT, &cfg.port);
565 break;
566 case IDC0_CLOSEEXIT:
567 if (HIWORD(wParam) == BN_CLICKED ||
568 HIWORD(wParam) == BN_DOUBLECLICKED)
569 cfg.close_on_exit = IsDlgButtonChecked (hwnd, IDC0_CLOSEEXIT);
570 break;
571 case IDC0_CLOSEWARN:
572 if (HIWORD(wParam) == BN_CLICKED ||
573 HIWORD(wParam) == BN_DOUBLECLICKED)
574 cfg.warn_on_close = IsDlgButtonChecked (hwnd, IDC0_CLOSEWARN);
575 break;
576 case IDC0_SESSEDIT:
577 if (HIWORD(wParam) == EN_CHANGE) {
578 SendDlgItemMessage (hwnd, IDC0_SESSLIST, LB_SETCURSEL,
579 (WPARAM) -1, 0);
580 GetDlgItemText (hwnd, IDC0_SESSEDIT,
581 savedsession, sizeof(savedsession)-1);
582 savedsession[sizeof(savedsession)-1] = '\0';
583 }
584 break;
585 case IDC0_SESSSAVE:
586 if (HIWORD(wParam) == BN_CLICKED ||
587 HIWORD(wParam) == BN_DOUBLECLICKED) {
588 /*
589 * Save a session
590 */
591 char str[2048];
592 GetDlgItemText (hwnd, IDC0_SESSEDIT, str, sizeof(str)-1);
593 if (!*str) {
594 int n = SendDlgItemMessage (hwnd, IDC0_SESSLIST,
595 LB_GETCURSEL, 0, 0);
596 if (n == LB_ERR) {
597 MessageBeep(0);
598 break;
599 }
600 strcpy (str, sessions[n]);
601 }
602 save_settings (str, !!strcmp(str, "Default Settings"));
603 get_sesslist (FALSE);
604 get_sesslist (TRUE);
605 SendDlgItemMessage (hwnd, IDC0_SESSLIST, LB_RESETCONTENT,
606 0, 0);
607 for (i = 0; i < nsessions; i++)
608 SendDlgItemMessage (hwnd, IDC0_SESSLIST, LB_ADDSTRING,
609 0, (LPARAM) (sessions[i]));
610 SendDlgItemMessage (hwnd, IDC0_SESSLIST, LB_SETCURSEL,
611 (WPARAM) -1, 0);
612 }
613 break;
614 case IDC0_SESSLIST:
615 case IDC0_SESSLOAD:
616 if (LOWORD(wParam) == IDC0_SESSLOAD &&
617 HIWORD(wParam) != BN_CLICKED &&
618 HIWORD(wParam) != BN_DOUBLECLICKED)
619 break;
620 if (LOWORD(wParam) == IDC0_SESSLIST &&
621 HIWORD(wParam) != LBN_DBLCLK)
622 break;
623 {
624 int n = SendDlgItemMessage (hwnd, IDC0_SESSLIST,
625 LB_GETCURSEL, 0, 0);
626 if (n == LB_ERR) {
627 MessageBeep(0);
628 break;
629 }
630 load_settings (sessions[n],
631 !!strcmp(sessions[n], "Default Settings"));
632 SetDlgItemText (hwnd, IDC0_HOST, cfg.host);
633 SetDlgItemInt (hwnd, IDC0_PORT, cfg.port, FALSE);
634 CheckRadioButton (hwnd, IDC0_PROTRAW, IDC0_PROTSSH,
635 (cfg.protocol==PROT_SSH ? IDC0_PROTSSH :
636 cfg.protocol==PROT_TELNET ? IDC0_PROTTELNET : IDC0_PROTRAW));
637 CheckDlgButton (hwnd, IDC0_CLOSEEXIT, cfg.close_on_exit);
638 CheckDlgButton (hwnd, IDC0_CLOSEWARN, cfg.warn_on_close);
639 SendDlgItemMessage (hwnd, IDC0_SESSLIST, LB_SETCURSEL,
640 (WPARAM) -1, 0);
641 }
642 if (LOWORD(wParam) == IDC0_SESSLIST) {
643 /*
644 * A double-click on a saved session should
645 * actually start the session, not just load it.
646 * Unless it's Default Settings or some other
647 * host-less set of saved settings.
648 */
649 if (*cfg.host) {
650 readytogo = TRUE;
651 SetCapture(hwnd);
652 }
653 }
654 break;
655 case IDC0_SESSDEL:
656 if (HIWORD(wParam) == BN_CLICKED ||
657 HIWORD(wParam) == BN_DOUBLECLICKED) {
658 int n = SendDlgItemMessage (hwnd, IDC0_SESSLIST,
659 LB_GETCURSEL, 0, 0);
660 if (n == LB_ERR || n == 0) {
661 MessageBeep(0);
662 break;
663 }
664 del_session(sessions[n]);
665 get_sesslist (FALSE);
666 get_sesslist (TRUE);
667 SendDlgItemMessage (hwnd, IDC0_SESSLIST, LB_RESETCONTENT,
668 0, 0);
669 for (i = 0; i < nsessions; i++)
670 SendDlgItemMessage (hwnd, IDC0_SESSLIST, LB_ADDSTRING,
671 0, (LPARAM) (sessions[i]));
672 SendDlgItemMessage (hwnd, IDC0_SESSLIST, LB_SETCURSEL,
673 (WPARAM) -1, 0);
674 }
675 }
676 }
677 return GeneralPanelProc (hwnd, msg, wParam, lParam);
678 }
679
680 static int CALLBACK KeyboardProc (HWND hwnd, UINT msg,
681 WPARAM wParam, LPARAM lParam) {
682 switch (msg) {
683 case WM_INITDIALOG:
684 CheckRadioButton (hwnd, IDC1_DEL008, IDC1_DEL127,
685 cfg.bksp_is_delete ? IDC1_DEL127 : IDC1_DEL008);
686 CheckRadioButton (hwnd, IDC1_HOMETILDE, IDC1_HOMERXVT,
687 cfg.rxvt_homeend ? IDC1_HOMERXVT : IDC1_HOMETILDE);
688 CheckRadioButton (hwnd, IDC1_FUNCTILDE, IDC1_FUNCXTERM,
689 cfg.funky_type ?
690 (cfg.funky_type==2 ? IDC1_FUNCXTERM
691 : IDC1_FUNCLINUX )
692 : IDC1_FUNCTILDE);
693 CheckRadioButton (hwnd, IDC1_CURNORMAL, IDC1_CURAPPLIC,
694 cfg.app_cursor ? IDC1_CURAPPLIC : IDC1_CURNORMAL);
695 CheckRadioButton (hwnd, IDC1_KPNORMAL, IDC1_KPNH,
696 cfg.nethack_keypad ? IDC1_KPNH :
697 cfg.app_keypad ? IDC1_KPAPPLIC : IDC1_KPNORMAL);
698 CheckDlgButton (hwnd, IDC1_ALTF4, cfg.alt_f4);
699 CheckDlgButton (hwnd, IDC1_ALTSPACE, cfg.alt_space);
700 CheckDlgButton (hwnd, IDC1_LDISCTERM, cfg.ldisc_term);
701 CheckDlgButton (hwnd, IDC1_SCROLLKEY, cfg.scroll_on_key);
702 break;
703 case WM_COMMAND:
704 if (HIWORD(wParam) == BN_CLICKED ||
705 HIWORD(wParam) == BN_DOUBLECLICKED)
706 switch (LOWORD(wParam)) {
707 case IDC1_DEL008:
708 case IDC1_DEL127:
709 cfg.bksp_is_delete = IsDlgButtonChecked (hwnd, IDC1_DEL127);
710 break;
711 case IDC1_HOMETILDE:
712 case IDC1_HOMERXVT:
713 cfg.rxvt_homeend = IsDlgButtonChecked (hwnd, IDC1_HOMERXVT);
714 break;
715 case IDC1_FUNCXTERM:
716 cfg.funky_type = 2;
717 break;
718 case IDC1_FUNCTILDE:
719 case IDC1_FUNCLINUX:
720 cfg.funky_type = IsDlgButtonChecked (hwnd, IDC1_FUNCLINUX);
721 break;
722 case IDC1_KPNORMAL:
723 case IDC1_KPAPPLIC:
724 cfg.app_keypad = IsDlgButtonChecked (hwnd, IDC1_KPAPPLIC);
725 cfg.nethack_keypad = FALSE;
726 break;
727 case IDC1_KPNH:
728 cfg.app_keypad = FALSE;
729 cfg.nethack_keypad = TRUE;
730 break;
731 case IDC1_CURNORMAL:
732 case IDC1_CURAPPLIC:
733 cfg.app_cursor = IsDlgButtonChecked (hwnd, IDC1_CURAPPLIC);
734 break;
735 case IDC1_ALTF4:
736 if (HIWORD(wParam) == BN_CLICKED ||
737 HIWORD(wParam) == BN_DOUBLECLICKED)
738 cfg.alt_f4 = IsDlgButtonChecked (hwnd, IDC1_ALTF4);
739 break;
740 case IDC1_ALTSPACE:
741 if (HIWORD(wParam) == BN_CLICKED ||
742 HIWORD(wParam) == BN_DOUBLECLICKED)
743 cfg.alt_space = IsDlgButtonChecked (hwnd, IDC1_ALTSPACE);
744 break;
745 case IDC1_LDISCTERM:
746 if (HIWORD(wParam) == BN_CLICKED ||
747 HIWORD(wParam) == BN_DOUBLECLICKED)
748 cfg.ldisc_term = IsDlgButtonChecked (hwnd, IDC1_LDISCTERM);
749 break;
750 case IDC1_SCROLLKEY:
751 if (HIWORD(wParam) == BN_CLICKED ||
752 HIWORD(wParam) == BN_DOUBLECLICKED)
753 cfg.scroll_on_key = IsDlgButtonChecked (hwnd, IDC1_SCROLLKEY);
754 break;
755 }
756 }
757 return GeneralPanelProc (hwnd, msg, wParam, lParam);
758 }
759
760 static void fmtfont (char *buf) {
761 sprintf (buf, "Font: %s, ", cfg.font);
762 if (cfg.fontisbold)
763 strcat(buf, "bold, ");
764 if (cfg.fontheight == 0)
765 strcat (buf, "default height");
766 else
767 sprintf (buf+strlen(buf), "%d-%s",
768 (cfg.fontheight < 0 ? -cfg.fontheight : cfg.fontheight),
769 (cfg.fontheight < 0 ? "pixel" : "point"));
770 }
771
772 static int CALLBACK TerminalProc (HWND hwnd, UINT msg,
773 WPARAM wParam, LPARAM lParam) {
774 CHOOSEFONT cf;
775 LOGFONT lf;
776 char fontstatic[256];
777
778 switch (msg) {
779 case WM_INITDIALOG:
780 CheckDlgButton (hwnd, IDC2_WRAPMODE, cfg.wrap_mode);
781 CheckDlgButton (hwnd, IDC2_WINNAME, cfg.win_name_always);
782 CheckDlgButton (hwnd, IDC2_DECOM, cfg.dec_om);
783 CheckDlgButton (hwnd, IDC2_LFHASCR, cfg.lfhascr);
784 SetDlgItemInt (hwnd, IDC2_ROWSEDIT, cfg.height, FALSE);
785 SetDlgItemInt (hwnd, IDC2_COLSEDIT, cfg.width, FALSE);
786 SetDlgItemInt (hwnd, IDC2_SAVEEDIT, cfg.savelines, FALSE);
787 fmtfont (fontstatic);
788 SetDlgItemText (hwnd, IDC2_FONTSTATIC, fontstatic);
789 CheckDlgButton (hwnd, IDC1_BLINKCUR, cfg.blink_cur);
790 CheckDlgButton (hwnd, IDC1_BEEP, cfg.beep);
791 CheckDlgButton (hwnd, IDC2_SCROLLBAR, cfg.scrollbar);
792 CheckDlgButton (hwnd, IDC2_LOCKSIZE, cfg.locksize);
793 CheckDlgButton (hwnd, IDC2_BCE, cfg.bce);
794 CheckDlgButton (hwnd, IDC2_BLINKTEXT, cfg.blinktext);
795 break;
796 case WM_COMMAND:
797 switch (LOWORD(wParam)) {
798 case IDC2_WRAPMODE:
799 if (HIWORD(wParam) == BN_CLICKED ||
800 HIWORD(wParam) == BN_DOUBLECLICKED)
801 cfg.wrap_mode = IsDlgButtonChecked (hwnd, IDC2_WRAPMODE);
802 break;
803 case IDC2_WINNAME:
804 if (HIWORD(wParam) == BN_CLICKED ||
805 HIWORD(wParam) == BN_DOUBLECLICKED)
806 cfg.win_name_always = IsDlgButtonChecked (hwnd, IDC2_WINNAME);
807 break;
808 case IDC2_DECOM:
809 if (HIWORD(wParam) == BN_CLICKED ||
810 HIWORD(wParam) == BN_DOUBLECLICKED)
811 cfg.dec_om = IsDlgButtonChecked (hwnd, IDC2_DECOM);
812 break;
813 case IDC2_LFHASCR:
814 if (HIWORD(wParam) == BN_CLICKED ||
815 HIWORD(wParam) == BN_DOUBLECLICKED)
816 cfg.lfhascr = IsDlgButtonChecked (hwnd, IDC2_LFHASCR);
817 break;
818 case IDC2_ROWSEDIT:
819 if (HIWORD(wParam) == EN_CHANGE)
820 MyGetDlgItemInt (hwnd, IDC2_ROWSEDIT, &cfg.height);
821 break;
822 case IDC2_COLSEDIT:
823 if (HIWORD(wParam) == EN_CHANGE)
824 MyGetDlgItemInt (hwnd, IDC2_COLSEDIT, &cfg.width);
825 break;
826 case IDC2_SAVEEDIT:
827 if (HIWORD(wParam) == EN_CHANGE)
828 MyGetDlgItemInt (hwnd, IDC2_SAVEEDIT, &cfg.savelines);
829 break;
830 case IDC2_CHOOSEFONT:
831 lf.lfHeight = cfg.fontheight;
832 lf.lfWidth = lf.lfEscapement = lf.lfOrientation = 0;
833 lf.lfItalic = lf.lfUnderline = lf.lfStrikeOut = 0;
834 lf.lfWeight = (cfg.fontisbold ? FW_BOLD : 0);
835 lf.lfCharSet = cfg.fontcharset;
836 lf.lfOutPrecision = OUT_DEFAULT_PRECIS;
837 lf.lfClipPrecision = CLIP_DEFAULT_PRECIS;
838 lf.lfQuality = DEFAULT_QUALITY;
839 lf.lfPitchAndFamily = FIXED_PITCH | FF_DONTCARE;
840 strncpy (lf.lfFaceName, cfg.font, sizeof(lf.lfFaceName)-1);
841 lf.lfFaceName[sizeof(lf.lfFaceName)-1] = '\0';
842
843 cf.lStructSize = sizeof(cf);
844 cf.hwndOwner = hwnd;
845 cf.lpLogFont = &lf;
846 cf.Flags = CF_FIXEDPITCHONLY | CF_FORCEFONTEXIST |
847 CF_INITTOLOGFONTSTRUCT | CF_SCREENFONTS;
848
849 if (ChooseFont (&cf)) {
850 strncpy (cfg.font, lf.lfFaceName, sizeof(cfg.font)-1);
851 cfg.font[sizeof(cfg.font)-1] = '\0';
852 cfg.fontisbold = (lf.lfWeight == FW_BOLD);
853 cfg.fontcharset = lf.lfCharSet;
854 cfg.fontheight = lf.lfHeight;
855 fmtfont (fontstatic);
856 SetDlgItemText (hwnd, IDC2_FONTSTATIC, fontstatic);
857 }
858 break;
859 case IDC1_BLINKCUR:
860 if (HIWORD(wParam) == BN_CLICKED ||
861 HIWORD(wParam) == BN_DOUBLECLICKED)
862 cfg.blink_cur = IsDlgButtonChecked (hwnd, IDC1_BLINKCUR);
863 break;
864 case IDC1_BEEP:
865 if (HIWORD(wParam) == BN_CLICKED ||
866 HIWORD(wParam) == BN_DOUBLECLICKED)
867 cfg.beep = IsDlgButtonChecked (hwnd, IDC1_BEEP);
868 break;
869 case IDC2_SCROLLBAR:
870 if (HIWORD(wParam) == BN_CLICKED ||
871 HIWORD(wParam) == BN_DOUBLECLICKED)
872 cfg.scrollbar = IsDlgButtonChecked (hwnd, IDC2_SCROLLBAR);
873 break;
874 case IDC2_LOCKSIZE:
875 if (HIWORD(wParam) == BN_CLICKED ||
876 HIWORD(wParam) == BN_DOUBLECLICKED)
877 cfg.locksize = IsDlgButtonChecked (hwnd, IDC2_LOCKSIZE);
878 break;
879 case IDC2_BLINKTEXT:
880 if (HIWORD(wParam) == BN_CLICKED ||
881 HIWORD(wParam) == BN_DOUBLECLICKED)
882 cfg.blinktext = IsDlgButtonChecked (hwnd, IDC2_BLINKTEXT);
883 break;
884 case IDC2_BCE:
885 if (HIWORD(wParam) == BN_CLICKED ||
886 HIWORD(wParam) == BN_DOUBLECLICKED)
887 cfg.bce = IsDlgButtonChecked (hwnd, IDC2_BCE);
888 break;
889 }
890 break;
891 }
892 return GeneralPanelProc (hwnd, msg, wParam, lParam);
893 }
894
895 static int CALLBACK TelnetProc (HWND hwnd, UINT msg,
896 WPARAM wParam, LPARAM lParam) {
897 int i;
898
899 switch (msg) {
900 case WM_INITDIALOG:
901 SetDlgItemText (hwnd, IDC3_TTEDIT, cfg.termtype);
902 SetDlgItemText (hwnd, IDC3_TSEDIT, cfg.termspeed);
903 SetDlgItemText (hwnd, IDC3_LOGEDIT, cfg.username);
904 {
905 char *p = cfg.environmt;
906 while (*p) {
907 SendDlgItemMessage (hwnd, IDC3_ENVLIST, LB_ADDSTRING, 0,
908 (LPARAM) p);
909 p += strlen(p)+1;
910 }
911 }
912 CheckRadioButton (hwnd, IDC3_EMBSD, IDC3_EMRFC,
913 cfg.rfc_environ ? IDC3_EMRFC : IDC3_EMBSD);
914 break;
915 case WM_COMMAND:
916 switch (LOWORD(wParam)) {
917 case IDC3_TTEDIT:
918 if (HIWORD(wParam) == EN_CHANGE)
919 GetDlgItemText (hwnd, IDC3_TTEDIT, cfg.termtype,
920 sizeof(cfg.termtype)-1);
921 break;
922 case IDC3_TSEDIT:
923 if (HIWORD(wParam) == EN_CHANGE)
924 GetDlgItemText (hwnd, IDC3_TSEDIT, cfg.termspeed,
925 sizeof(cfg.termspeed)-1);
926 break;
927 case IDC3_LOGEDIT:
928 if (HIWORD(wParam) == EN_CHANGE)
929 GetDlgItemText (hwnd, IDC3_LOGEDIT, cfg.username,
930 sizeof(cfg.username)-1);
931 break;
932 case IDC3_EMBSD:
933 case IDC3_EMRFC:
934 cfg.rfc_environ = IsDlgButtonChecked (hwnd, IDC3_EMRFC);
935 break;
936 case IDC3_ENVADD:
937 if (HIWORD(wParam) == BN_CLICKED ||
938 HIWORD(wParam) == BN_DOUBLECLICKED) {
939 char str[sizeof(cfg.environmt)];
940 char *p;
941 GetDlgItemText (hwnd, IDC3_VAREDIT, str, sizeof(str)-1);
942 if (!*str) {
943 MessageBeep(0);
944 break;
945 }
946 p = str + strlen(str);
947 *p++ = '\t';
948 GetDlgItemText (hwnd, IDC3_VALEDIT, p, sizeof(str)-1-(p-str));
949 if (!*p) {
950 MessageBeep(0);
951 break;
952 }
953 p = cfg.environmt;
954 while (*p) {
955 while (*p) p++;
956 p++;
957 }
958 if ((p-cfg.environmt) + strlen(str) + 2 < sizeof(cfg.environmt)) {
959 strcpy (p, str);
960 p[strlen(str)+1] = '\0';
961 SendDlgItemMessage (hwnd, IDC3_ENVLIST, LB_ADDSTRING,
962 0, (LPARAM)str);
963 SetDlgItemText (hwnd, IDC3_VAREDIT, "");
964 SetDlgItemText (hwnd, IDC3_VALEDIT, "");
965 } else {
966 MessageBox(hwnd, "Environment too big", "PuTTY Error",
967 MB_OK | MB_ICONERROR);
968 }
969 }
970 break;
971 case IDC3_ENVREMOVE:
972 if (HIWORD(wParam) != BN_CLICKED &&
973 HIWORD(wParam) != BN_DOUBLECLICKED)
974 break;
975 i = SendDlgItemMessage (hwnd, IDC3_ENVLIST, LB_GETCURSEL, 0, 0);
976 if (i == LB_ERR)
977 MessageBeep (0);
978 else {
979 char *p, *q;
980
981 SendDlgItemMessage (hwnd, IDC3_ENVLIST, LB_DELETESTRING,
982 i, 0);
983 p = cfg.environmt;
984 while (i > 0) {
985 if (!*p)
986 goto disaster;
987 while (*p) p++;
988 p++;
989 i--;
990 }
991 q = p;
992 if (!*p)
993 goto disaster;
994 while (*p) p++;
995 p++;
996 while (*p) {
997 while (*p)
998 *q++ = *p++;
999 *q++ = *p++;
1000 }
1001 *q = '\0';
1002 disaster:;
1003 }
1004 break;
1005 }
1006 break;
1007 }
1008 return GeneralPanelProc (hwnd, msg, wParam, lParam);
1009 }
1010
1011 static int CALLBACK SshProc (HWND hwnd, UINT msg,
1012 WPARAM wParam, LPARAM lParam) {
1013 OPENFILENAME of;
1014 char filename[sizeof(cfg.keyfile)];
1015
1016 switch (msg) {
1017 case WM_INITDIALOG:
1018 SetDlgItemText (hwnd, IDC3_TTEDIT, cfg.termtype);
1019 SetDlgItemText (hwnd, IDC3_LOGEDIT, cfg.username);
1020 CheckDlgButton (hwnd, IDC3_NOPTY, cfg.nopty);
1021 CheckDlgButton (hwnd, IDC3_AGENTFWD, cfg.agentfwd);
1022 CheckRadioButton (hwnd, IDC3_CIPHER3DES, IDC3_CIPHERDES,
1023 cfg.cipher == CIPHER_BLOWFISH ? IDC3_CIPHERBLOWF :
1024 cfg.cipher == CIPHER_DES ? IDC3_CIPHERDES :
1025 IDC3_CIPHER3DES);
1026 CheckRadioButton (hwnd, IDC3_SSHPROT1, IDC3_SSHPROT2,
1027 cfg.sshprot == 1 ? IDC3_SSHPROT1 : IDC3_SSHPROT2);
1028 CheckDlgButton (hwnd, IDC3_AUTHTIS, cfg.try_tis_auth);
1029 SetDlgItemText (hwnd, IDC3_PKEDIT, cfg.keyfile);
1030 break;
1031 case WM_COMMAND:
1032 switch (LOWORD(wParam)) {
1033 case IDC3_TTEDIT:
1034 if (HIWORD(wParam) == EN_CHANGE)
1035 GetDlgItemText (hwnd, IDC3_TTEDIT, cfg.termtype,
1036 sizeof(cfg.termtype)-1);
1037 break;
1038 case IDC3_LOGEDIT:
1039 if (HIWORD(wParam) == EN_CHANGE)
1040 GetDlgItemText (hwnd, IDC3_LOGEDIT, cfg.username,
1041 sizeof(cfg.username)-1);
1042 break;
1043 case IDC3_NOPTY:
1044 if (HIWORD(wParam) == BN_CLICKED ||
1045 HIWORD(wParam) == BN_DOUBLECLICKED)
1046 cfg.nopty = IsDlgButtonChecked (hwnd, IDC3_NOPTY);
1047 break;
1048 case IDC3_AGENTFWD:
1049 if (HIWORD(wParam) == BN_CLICKED ||
1050 HIWORD(wParam) == BN_DOUBLECLICKED)
1051 cfg.agentfwd = IsDlgButtonChecked (hwnd, IDC3_AGENTFWD);
1052 break;
1053 case IDC3_CIPHER3DES:
1054 case IDC3_CIPHERBLOWF:
1055 case IDC3_CIPHERDES:
1056 if (HIWORD(wParam) == BN_CLICKED ||
1057 HIWORD(wParam) == BN_DOUBLECLICKED) {
1058 if (IsDlgButtonChecked (hwnd, IDC3_CIPHER3DES))
1059 cfg.cipher = CIPHER_3DES;
1060 else if (IsDlgButtonChecked (hwnd, IDC3_CIPHERBLOWF))
1061 cfg.cipher = CIPHER_BLOWFISH;
1062 else if (IsDlgButtonChecked (hwnd, IDC3_CIPHERDES))
1063 cfg.cipher = CIPHER_DES;
1064 }
1065 break;
1066 case IDC3_SSHPROT1:
1067 case IDC3_SSHPROT2:
1068 if (HIWORD(wParam) == BN_CLICKED ||
1069 HIWORD(wParam) == BN_DOUBLECLICKED) {
1070 if (IsDlgButtonChecked (hwnd, IDC3_SSHPROT1))
1071 cfg.sshprot = 1;
1072 else if (IsDlgButtonChecked (hwnd, IDC3_SSHPROT2))
1073 cfg.sshprot = 2;
1074 }
1075 break;
1076 case IDC3_AUTHTIS:
1077 if (HIWORD(wParam) == BN_CLICKED ||
1078 HIWORD(wParam) == BN_DOUBLECLICKED)
1079 cfg.try_tis_auth = IsDlgButtonChecked (hwnd, IDC3_AUTHTIS);
1080 break;
1081 case IDC3_PKEDIT:
1082 if (HIWORD(wParam) == EN_CHANGE)
1083 GetDlgItemText (hwnd, IDC3_PKEDIT, cfg.keyfile,
1084 sizeof(cfg.keyfile)-1);
1085 break;
1086 case IDC3_PKBUTTON:
1087 /*
1088 * FIXME: this crashes. Find out why.
1089 */
1090 memset(&of, 0, sizeof(of));
1091 #ifdef OPENFILENAME_SIZE_VERSION_400
1092 of.lStructSize = OPENFILENAME_SIZE_VERSION_400;
1093 #else
1094 of.lStructSize = sizeof(of);
1095 #endif
1096 of.hwndOwner = hwnd;
1097 of.lpstrFilter = "All Files\0*\0\0\0";
1098 of.lpstrCustomFilter = NULL;
1099 of.nFilterIndex = 1;
1100 of.lpstrFile = filename; strcpy(filename, cfg.keyfile);
1101 of.nMaxFile = sizeof(filename);
1102 of.lpstrFileTitle = NULL;
1103 of.lpstrInitialDir = NULL;
1104 of.lpstrTitle = "Select Public Key File";
1105 of.Flags = 0;
1106 if (GetOpenFileName(&of)) {
1107 strcpy(cfg.keyfile, filename);
1108 SetDlgItemText (hwnd, IDC3_PKEDIT, cfg.keyfile);
1109 }
1110 break;
1111 }
1112 break;
1113 }
1114 return GeneralPanelProc (hwnd, msg, wParam, lParam);
1115 }
1116
1117 static int CALLBACK SelectionProc (HWND hwnd, UINT msg,
1118 WPARAM wParam, LPARAM lParam) {
1119 int i;
1120
1121 switch (msg) {
1122 case WM_INITDIALOG:
1123 CheckRadioButton (hwnd, IDC4_MBWINDOWS, IDC4_MBXTERM,
1124 cfg.mouse_is_xterm ? IDC4_MBXTERM : IDC4_MBWINDOWS);
1125 {
1126 static int tabs[4] = {25, 61, 96, 128};
1127 SendDlgItemMessage (hwnd, IDC4_CCLIST, LB_SETTABSTOPS, 4,
1128 (LPARAM) tabs);
1129 }
1130 for (i=0; i<256; i++) {
1131 char str[100];
1132 sprintf(str, "%d\t(0x%02X)\t%c\t%d", i, i,
1133 (i>=0x21 && i != 0x7F) ? i : ' ',
1134 cfg.wordness[i]);
1135 SendDlgItemMessage (hwnd, IDC4_CCLIST, LB_ADDSTRING, 0,
1136 (LPARAM) str);
1137 }
1138 break;
1139 case WM_COMMAND:
1140 switch (LOWORD(wParam)) {
1141 case IDC4_MBWINDOWS:
1142 case IDC4_MBXTERM:
1143 cfg.mouse_is_xterm = IsDlgButtonChecked (hwnd, IDC4_MBXTERM);
1144 break;
1145 case IDC4_CCSET:
1146 {
1147 BOOL ok;
1148 int i;
1149 int n = GetDlgItemInt (hwnd, IDC4_CCEDIT, &ok, FALSE);
1150
1151 if (!ok)
1152 MessageBeep (0);
1153 else {
1154 for (i=0; i<256; i++)
1155 if (SendDlgItemMessage (hwnd, IDC4_CCLIST, LB_GETSEL,
1156 i, 0)) {
1157 char str[100];
1158 cfg.wordness[i] = n;
1159 SendDlgItemMessage (hwnd, IDC4_CCLIST,
1160 LB_DELETESTRING, i, 0);
1161 sprintf(str, "%d\t(0x%02X)\t%c\t%d", i, i,
1162 (i>=0x21 && i != 0x7F) ? i : ' ',
1163 cfg.wordness[i]);
1164 SendDlgItemMessage (hwnd, IDC4_CCLIST,
1165 LB_INSERTSTRING, i,
1166 (LPARAM)str);
1167 }
1168 }
1169 }
1170 break;
1171 }
1172 break;
1173 }
1174 return GeneralPanelProc (hwnd, msg, wParam, lParam);
1175 }
1176
1177 static int CALLBACK ColourProc (HWND hwnd, UINT msg,
1178 WPARAM wParam, LPARAM lParam) {
1179 static const char *const colours[] = {
1180 "Default Foreground", "Default Bold Foreground",
1181 "Default Background", "Default Bold Background",
1182 "Cursor Text", "Cursor Colour",
1183 "ANSI Black", "ANSI Black Bold",
1184 "ANSI Red", "ANSI Red Bold",
1185 "ANSI Green", "ANSI Green Bold",
1186 "ANSI Yellow", "ANSI Yellow Bold",
1187 "ANSI Blue", "ANSI Blue Bold",
1188 "ANSI Magenta", "ANSI Magenta Bold",
1189 "ANSI Cyan", "ANSI Cyan Bold",
1190 "ANSI White", "ANSI White Bold"
1191 };
1192 static const int permanent[] = {
1193 TRUE, FALSE, TRUE, FALSE, TRUE, TRUE,
1194 TRUE, FALSE, TRUE, FALSE, TRUE, FALSE, TRUE, FALSE,
1195 TRUE, FALSE, TRUE, FALSE, TRUE, FALSE, TRUE, FALSE
1196 };
1197 switch (msg) {
1198 case WM_INITDIALOG:
1199 CheckDlgButton (hwnd, IDC5_BOLDCOLOUR, cfg.bold_colour);
1200 CheckDlgButton (hwnd, IDC5_PALETTE, cfg.try_palette);
1201 {
1202 int i;
1203 for (i=0; i<22; i++)
1204 if (cfg.bold_colour || permanent[i])
1205 SendDlgItemMessage (hwnd, IDC5_LIST, LB_ADDSTRING, 0,
1206 (LPARAM) colours[i]);
1207 }
1208 SendDlgItemMessage (hwnd, IDC5_LIST, LB_SETCURSEL, 0, 0);
1209 SetDlgItemInt (hwnd, IDC5_RVALUE, cfg.colours[0][0], FALSE);
1210 SetDlgItemInt (hwnd, IDC5_GVALUE, cfg.colours[0][1], FALSE);
1211 SetDlgItemInt (hwnd, IDC5_BVALUE, cfg.colours[0][2], FALSE);
1212 break;
1213 case WM_COMMAND:
1214 switch (LOWORD(wParam)) {
1215 case IDC5_BOLDCOLOUR:
1216 if (HIWORD(wParam) == BN_CLICKED ||
1217 HIWORD(wParam) == BN_DOUBLECLICKED) {
1218 int n, i;
1219 cfg.bold_colour = IsDlgButtonChecked (hwnd, IDC5_BOLDCOLOUR);
1220 n = SendDlgItemMessage (hwnd, IDC5_LIST, LB_GETCOUNT, 0, 0);
1221 if (cfg.bold_colour && n!=22) {
1222 for (i=0; i<22; i++)
1223 if (!permanent[i])
1224 SendDlgItemMessage (hwnd, IDC5_LIST,
1225 LB_INSERTSTRING, i,
1226 (LPARAM) colours[i]);
1227 } else if (!cfg.bold_colour && n!=12) {
1228 for (i=22; i-- ;)
1229 if (!permanent[i])
1230 SendDlgItemMessage (hwnd, IDC5_LIST,
1231 LB_DELETESTRING, i, 0);
1232 }
1233 }
1234 break;
1235 case IDC5_PALETTE:
1236 if (HIWORD(wParam) == BN_CLICKED ||
1237 HIWORD(wParam) == BN_DOUBLECLICKED)
1238 cfg.try_palette = IsDlgButtonChecked (hwnd, IDC5_PALETTE);
1239 break;
1240 case IDC5_LIST:
1241 if (HIWORD(wParam) == LBN_DBLCLK ||
1242 HIWORD(wParam) == LBN_SELCHANGE) {
1243 int i = SendDlgItemMessage (hwnd, IDC5_LIST, LB_GETCURSEL,
1244 0, 0);
1245 if (!cfg.bold_colour)
1246 i = (i < 3 ? i*2 : i == 3 ? 5 : i*2-2);
1247 SetDlgItemInt (hwnd, IDC5_RVALUE, cfg.colours[i][0], FALSE);
1248 SetDlgItemInt (hwnd, IDC5_GVALUE, cfg.colours[i][1], FALSE);
1249 SetDlgItemInt (hwnd, IDC5_BVALUE, cfg.colours[i][2], FALSE);
1250 }
1251 break;
1252 case IDC5_CHANGE:
1253 if (HIWORD(wParam) == BN_CLICKED ||
1254 HIWORD(wParam) == BN_DOUBLECLICKED) {
1255 static CHOOSECOLOR cc;
1256 static DWORD custom[16] = {0}; /* zero initialisers */
1257 int i = SendDlgItemMessage (hwnd, IDC5_LIST, LB_GETCURSEL,
1258 0, 0);
1259 if (!cfg.bold_colour)
1260 i = (i < 3 ? i*2 : i == 3 ? 5 : i*2-2);
1261 cc.lStructSize = sizeof(cc);
1262 cc.hwndOwner = hwnd;
1263 cc.hInstance = (HWND)hinst;
1264 cc.lpCustColors = custom;
1265 cc.rgbResult = RGB (cfg.colours[i][0], cfg.colours[i][1],
1266 cfg.colours[i][2]);
1267 cc.Flags = CC_FULLOPEN | CC_RGBINIT;
1268 if (ChooseColor(&cc)) {
1269 cfg.colours[i][0] =
1270 (unsigned char) (cc.rgbResult & 0xFF);
1271 cfg.colours[i][1] =
1272 (unsigned char) (cc.rgbResult >> 8) & 0xFF;
1273 cfg.colours[i][2] =
1274 (unsigned char) (cc.rgbResult >> 16) & 0xFF;
1275 SetDlgItemInt (hwnd, IDC5_RVALUE, cfg.colours[i][0],
1276 FALSE);
1277 SetDlgItemInt (hwnd, IDC5_GVALUE, cfg.colours[i][1],
1278 FALSE);
1279 SetDlgItemInt (hwnd, IDC5_BVALUE, cfg.colours[i][2],
1280 FALSE);
1281 }
1282 }
1283 break;
1284 }
1285 break;
1286 }
1287 return GeneralPanelProc (hwnd, msg, wParam, lParam);
1288 }
1289
1290 static int CALLBACK TranslationProc (HWND hwnd, UINT msg,
1291 WPARAM wParam, LPARAM lParam) {
1292 switch (msg) {
1293 case WM_INITDIALOG:
1294 CheckRadioButton (hwnd, IDC6_NOXLAT, IDC6_88592WIN1250,
1295 cfg.xlat_88592w1250 ? IDC6_88592WIN1250 :
1296 cfg.xlat_enablekoiwin ? IDC6_KOI8WIN1251 :
1297 IDC6_NOXLAT);
1298 CheckDlgButton (hwnd, IDC6_CAPSLOCKCYR, cfg.xlat_capslockcyr);
1299 CheckRadioButton (hwnd, IDC2_VTXWINDOWS, IDC2_VTPOORMAN,
1300 cfg.vtmode == VT_XWINDOWS ? IDC2_VTXWINDOWS :
1301 cfg.vtmode == VT_OEMANSI ? IDC2_VTOEMANSI :
1302 cfg.vtmode == VT_OEMONLY ? IDC2_VTOEMONLY :
1303 IDC2_VTPOORMAN);
1304 case WM_COMMAND:
1305 switch (LOWORD(wParam)) {
1306 case IDC6_NOXLAT:
1307 case IDC6_KOI8WIN1251:
1308 case IDC6_88592WIN1250:
1309 cfg.xlat_enablekoiwin =
1310 IsDlgButtonChecked (hwnd, IDC6_KOI8WIN1251);
1311 cfg.xlat_88592w1250 =
1312 IsDlgButtonChecked (hwnd, IDC6_88592WIN1250);
1313 break;
1314 case IDC6_CAPSLOCKCYR:
1315 if (HIWORD(wParam) == BN_CLICKED ||
1316 HIWORD(wParam) == BN_DOUBLECLICKED) {
1317 cfg.xlat_capslockcyr =
1318 IsDlgButtonChecked (hwnd, IDC6_CAPSLOCKCYR);
1319 }
1320 break;
1321 case IDC2_VTXWINDOWS:
1322 case IDC2_VTOEMANSI:
1323 case IDC2_VTOEMONLY:
1324 case IDC2_VTPOORMAN:
1325 cfg.vtmode =
1326 (IsDlgButtonChecked (hwnd, IDC2_VTXWINDOWS) ? VT_XWINDOWS :
1327 IsDlgButtonChecked (hwnd, IDC2_VTOEMANSI) ? VT_OEMANSI :
1328 IsDlgButtonChecked (hwnd, IDC2_VTOEMONLY) ? VT_OEMONLY :
1329 VT_POORMAN);
1330 break;
1331 }
1332 }
1333 return GeneralPanelProc (hwnd, msg, wParam, lParam);
1334 }
1335
1336 static DLGPROC panelproc[NPANELS] = {
1337 ConnectionProc, KeyboardProc, TerminalProc,
1338 TelnetProc, SshProc, SelectionProc, ColourProc, TranslationProc
1339 };
1340 static char *panelids[NPANELS] = {
1341 MAKEINTRESOURCE(IDD_PANEL0),
1342 MAKEINTRESOURCE(IDD_PANEL1),
1343 MAKEINTRESOURCE(IDD_PANEL2),
1344 MAKEINTRESOURCE(IDD_PANEL3),
1345 MAKEINTRESOURCE(IDD_PANEL35),
1346 MAKEINTRESOURCE(IDD_PANEL4),
1347 MAKEINTRESOURCE(IDD_PANEL5),
1348 MAKEINTRESOURCE(IDD_PANEL6)
1349 };
1350
1351 static char *names[NPANELS] = {
1352 "Connection", "Keyboard", "Terminal", "Telnet",
1353 "SSH", "Selection", "Colours", "Translation"
1354 };
1355
1356 static int mainp[MAIN_NPANELS] = { 0, 1, 2, 3, 4, 5, 6, 7};
1357 static int reconfp[RECONF_NPANELS] = { 1, 2, 5, 6, 7};
1358
1359 static int GenericMainDlgProc (HWND hwnd, UINT msg,
1360 WPARAM wParam, LPARAM lParam,
1361 int npanels, int *panelnums, HWND *page) {
1362 HWND hw;
1363
1364 switch (msg) {
1365 case WM_INITDIALOG:
1366 { /* centre the window */
1367 RECT rs, rd;
1368
1369 hw = GetDesktopWindow();
1370 if (GetWindowRect (hw, &rs) && GetWindowRect (hwnd, &rd))
1371 MoveWindow (hwnd, (rs.right + rs.left + rd.left - rd.right)/2,
1372 (rs.bottom + rs.top + rd.top - rd.bottom)/2,
1373 rd.right-rd.left, rd.bottom-rd.top, TRUE);
1374 }
1375 *page = NULL;
1376 { /* initialise the tab control */
1377 TC_ITEMHEADER tab;
1378 int i;
1379
1380 hw = GetDlgItem (hwnd, IDC_TAB);
1381 for (i=0; i<npanels; i++) {
1382 tab.mask = TCIF_TEXT;
1383 tab.pszText = names[panelnums[i]];
1384 TabCtrl_InsertItem (hw, i, &tab);
1385 }
1386 /* *page = CreateDialogIndirect (hinst, panels[panelnums[0]].temp,
1387 hwnd, panelproc[panelnums[0]]);*/
1388 *page = CreateDialog (hinst, panelids[panelnums[0]],
1389 hwnd, panelproc[panelnums[0]]);
1390 SetWindowLong (*page, GWL_EXSTYLE,
1391 GetWindowLong (*page, GWL_EXSTYLE) |
1392 WS_EX_CONTROLPARENT);
1393 }
1394 SetFocus (*page);
1395 return 0;
1396 case WM_NOTIFY:
1397 if (LOWORD(wParam) == IDC_TAB &&
1398 ((LPNMHDR)lParam)->code == TCN_SELCHANGE) {
1399 int i = TabCtrl_GetCurSel(((LPNMHDR)lParam)->hwndFrom);
1400 if (*page)
1401 DestroyWindow (*page);
1402 /* *page = CreateDialogIndirect (hinst, panels[panelnums[i]].temp,
1403 hwnd, panelproc[panelnums[i]]);*/
1404 *page = CreateDialog (hinst, panelids[panelnums[i]],
1405 hwnd, panelproc[panelnums[i]]);
1406 SetWindowLong (*page, GWL_EXSTYLE,
1407 GetWindowLong (*page, GWL_EXSTYLE) |
1408 WS_EX_CONTROLPARENT);
1409 SetFocus (((LPNMHDR)lParam)->hwndFrom); /* ensure focus stays */
1410 return 0;
1411 }
1412 break;
1413 /* case WM_CTLCOLORDLG: */
1414 /* return (int) GetStockObject (LTGRAY_BRUSH); */
1415 case WM_COMMAND:
1416 switch (LOWORD(wParam)) {
1417 case IDOK:
1418 if (*cfg.host)
1419 EndDialog (hwnd, 1);
1420 else
1421 MessageBeep (0);
1422 return 0;
1423 case IDCANCEL:
1424 EndDialog (hwnd, 0);
1425 return 0;
1426 }
1427 return 0;
1428 case WM_CLOSE:
1429 EndDialog (hwnd, 0);
1430 return 0;
1431
1432 /* Grrr Explorer will maximize Dialogs! */
1433 case WM_SIZE:
1434 if (wParam == SIZE_MAXIMIZED)
1435 force_normal(hwnd);
1436 return 0;
1437 }
1438 return 0;
1439 }
1440
1441 static int CALLBACK MainDlgProc (HWND hwnd, UINT msg,
1442 WPARAM wParam, LPARAM lParam) {
1443 #if 0
1444 HWND hw;
1445 int i;
1446 #endif
1447 static HWND page = NULL;
1448
1449 if (msg == WM_COMMAND && LOWORD(wParam) == IDOK) {
1450 #if 0
1451 /*
1452 * If the Connection panel is active and the Session List
1453 * box is selected, we treat a press of Open to have an
1454 * implicit press of Load preceding it.
1455 */
1456 hw = GetDlgItem (hwnd, IDC_TAB);
1457 i = TabCtrl_GetCurSel(hw);
1458 if (panelproc[mainp[i]] == ConnectionProc &&
1459 page && implicit_load_ok) {
1460 SendMessage (page, WM_COMMAND,
1461 MAKELONG(IDC0_SESSLOAD, BN_CLICKED), 0);
1462 }
1463 #endif
1464 }
1465 if (msg == WM_COMMAND && LOWORD(wParam) == IDC_ABOUT) {
1466 EnableWindow(hwnd, 0);
1467 DialogBox(hinst, MAKEINTRESOURCE(IDD_ABOUTBOX),
1468 GetParent(hwnd), AboutProc);
1469 EnableWindow(hwnd, 1);
1470 }
1471 return GenericMainDlgProc (hwnd, msg, wParam, lParam,
1472 MAIN_NPANELS, mainp, &page);
1473 }
1474
1475 static int CALLBACK ReconfDlgProc (HWND hwnd, UINT msg,
1476 WPARAM wParam, LPARAM lParam) {
1477 static HWND page;
1478 return GenericMainDlgProc (hwnd, msg, wParam, lParam,
1479 RECONF_NPANELS, reconfp, &page);
1480 }
1481
1482 void get_sesslist(int allocate) {
1483 static char *buffer;
1484 int buflen, bufsize, i, ret;
1485 char otherbuf[2048];
1486 char *p;
1487 HKEY subkey1;
1488
1489 if (allocate) {
1490 if (RegCreateKey(HKEY_CURRENT_USER,
1491 puttystr, &subkey1) != ERROR_SUCCESS)
1492 return;
1493
1494 buflen = bufsize = 0;
1495 buffer = NULL;
1496 i = 0;
1497 do {
1498 ret = RegEnumKey(subkey1, i++, otherbuf, sizeof(otherbuf));
1499 if (ret == ERROR_SUCCESS) {
1500 bufsize = buflen + 2048;
1501 buffer = srealloc(buffer, bufsize);
1502 unmungestr(otherbuf, buffer+buflen);
1503 buflen += strlen(buffer+buflen)+1;
1504 }
1505 } while (ret == ERROR_SUCCESS);
1506 buffer = srealloc(buffer, buflen+1);
1507 buffer[buflen] = '\0';
1508
1509 p = buffer;
1510 nsessions = 1; /* "Default Settings" counts as one */
1511 while (*p) {
1512 if (strcmp(p, "Default Settings"))
1513 nsessions++;
1514 while (*p) p++;
1515 p++;
1516 }
1517
1518 sessions = smalloc(nsessions * sizeof(char *));
1519 sessions[0] = "Default Settings";
1520 p = buffer;
1521 i = 1;
1522 while (*p) {
1523 if (strcmp(p, "Default Settings"))
1524 sessions[i++] = p;
1525 while (*p) p++;
1526 p++;
1527 }
1528 } else {
1529 sfree (buffer);
1530 sfree (sessions);
1531 }
1532 }
1533
1534 int do_config (void) {
1535 int ret;
1536
1537 get_sesslist(TRUE);
1538 savedsession[0] = '\0';
1539 ret = DialogBox (hinst, MAKEINTRESOURCE(IDD_MAINBOX), NULL, MainDlgProc);
1540 get_sesslist(FALSE);
1541
1542 return ret;
1543 }
1544
1545 int do_reconfig (HWND hwnd) {
1546 Config backup_cfg;
1547 int ret;
1548
1549 backup_cfg = cfg; /* structure copy */
1550 ret = DialogBox (hinst, MAKEINTRESOURCE(IDD_RECONF), hwnd, ReconfDlgProc);
1551 if (!ret)
1552 cfg = backup_cfg; /* structure copy */
1553 else
1554 force_normal(hwnd);
1555
1556 return ret;
1557 }
1558
1559 void do_defaults (char *session) {
1560 if (session)
1561 load_settings (session, TRUE);
1562 else
1563 load_settings ("Default Settings", FALSE);
1564 }
1565
1566 void logevent (char *string) {
1567 if (nevents >= negsize) {
1568 negsize += 64;
1569 events = srealloc (events, negsize * sizeof(*events));
1570 }
1571 events[nevents] = smalloc(1+strlen(string));
1572 strcpy (events[nevents], string);
1573 nevents++;
1574 if (logbox)
1575 SendDlgItemMessage (logbox, IDN_LIST, LB_ADDSTRING,
1576 0, (LPARAM)string);
1577 }
1578
1579 void showeventlog (HWND hwnd) {
1580 if (!logbox) {
1581 logbox = CreateDialog (hinst, MAKEINTRESOURCE(IDD_LOGBOX),
1582 hwnd, LogProc);
1583 ShowWindow (logbox, SW_SHOWNORMAL);
1584 }
1585 }
1586
1587 void showabout (HWND hwnd) {
1588 if (!abtbox) {
1589 abtbox = CreateDialog (hinst, MAKEINTRESOURCE(IDD_ABOUTBOX),
1590 hwnd, AboutProc);
1591 ShowWindow (abtbox, SW_SHOWNORMAL);
1592 }
1593 }
1594
1595 void verify_ssh_host_key(char *host, char *keystr) {
1596 char *otherstr, *mungedhost;
1597 int len;
1598 HKEY rkey;
1599
1600 len = 1 + strlen(keystr);
1601
1602 /*
1603 * Now read a saved key in from the registry and see what it
1604 * says.
1605 */
1606 otherstr = smalloc(len);
1607 mungedhost = smalloc(3*strlen(host)+1);
1608 if (!otherstr || !mungedhost)
1609 fatalbox("Out of memory");
1610
1611 mungestr(host, mungedhost);
1612
1613 if (RegCreateKey(HKEY_CURRENT_USER, PUTTY_REG_POS "\\SshHostKeys",
1614 &rkey) != ERROR_SUCCESS) {
1615 if (MessageBox(NULL, "PuTTY was unable to open the host key cache\n"
1616 "in the registry. There is thus no way to tell\n"
1617 "if the remote host is what you think it is.\n"
1618 "Connect anyway?", "PuTTY Problem",
1619 MB_ICONWARNING | MB_YESNO) == IDNO)
1620 exit(0);
1621 } else {
1622 DWORD readlen = len;
1623 DWORD type;
1624 int ret;
1625
1626 ret = RegQueryValueEx(rkey, mungedhost, NULL,
1627 &type, otherstr, &readlen);
1628
1629 if (ret == ERROR_MORE_DATA ||
1630 (ret == ERROR_SUCCESS && type == REG_SZ &&
1631 strcmp(otherstr, keystr))) {
1632 if (MessageBox(NULL,
1633 "This host's host key is different from the\n"
1634 "one cached in the registry! Someone may be\n"
1635 "impersonating this host for malicious reasons;\n"
1636 "alternatively, the host key may have changed\n"
1637 "due to sloppy system administration.\n"
1638 "Replace key in registry and connect?",
1639 "PuTTY: Security Warning",
1640 MB_ICONWARNING | MB_YESNO) == IDNO)
1641 exit(0);
1642 RegSetValueEx(rkey, mungedhost, 0, REG_SZ, keystr,
1643 strlen(keystr)+1);
1644 } else if (ret != ERROR_SUCCESS || type != REG_SZ) {
1645 if (MessageBox(NULL,
1646 "This host's host key is not cached in the\n"
1647 "registry. Do you want to add it to the cache\n"
1648 "and carry on connecting?",
1649 "PuTTY: New Host",
1650 MB_ICONWARNING | MB_YESNO) == IDNO)
1651 exit(0);
1652 RegSetValueEx(rkey, mungedhost, 0, REG_SZ, keystr,
1653 strlen(keystr)+1);
1654 }
1655
1656 RegCloseKey(rkey);
1657 }
1658 }