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