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