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