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