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