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